1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #include "SDCCpeeph.h"
59 char *aopLiteral (value * val, int offset);
62 /* this is the down and dirty file with all kinds of
63 kludgy & hacky stuff. This is what it is all about
64 CODE GENERATION for a specific MCU . some of the
65 routines may be reusable, will have to see */
67 static char *zero = "#0x00";
68 static char *one = "#0x01";
72 {"dpl", "dph", "b", "a"};
73 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
74 char **fReturn = fReturn8051;
75 static char *accUse[] =
78 static short rbank = -1;
92 extern int mcs51_ptrRegReq;
93 extern int mcs51_nRegs;
94 extern FILE *codeOutFile;
95 static void saveRBank (int, iCode *, bool);
96 #define RESULTONSTACK(x) \
97 (IC_RESULT(x) && IC_RESULT(x)->aop && \
98 IC_RESULT(x)->aop->type == AOP_STK )
100 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] =
108 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] =
111 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
112 0x07, 0x03, 0x01, 0x00};
119 /*-----------------------------------------------------------------*/
120 /* emitcode - writes the code into a file : for now it is simple */
121 /*-----------------------------------------------------------------*/
123 emitcode (char *inst, char *fmt,...)
126 char lb[INITIAL_INLINEASM];
134 sprintf (lb, "%s\t", inst);
136 sprintf (lb, "%s", inst);
137 vsprintf (lb + (strlen (lb)), fmt, ap);
140 vsprintf (lb, fmt, ap);
142 while (isspace (*lbp))
146 lineCurr = (lineCurr ?
147 connectLine (lineCurr, newLineNode (lb)) :
148 (lineHead = newLineNode (lb)));
149 lineCurr->isInline = _G.inLine;
150 lineCurr->isDebug = _G.debugLine;
154 /*-----------------------------------------------------------------*/
155 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
156 /*-----------------------------------------------------------------*/
158 getFreePtr (iCode * ic, asmop ** aopp, bool result)
160 bool r0iu = FALSE, r1iu = FALSE;
161 bool r0ou = FALSE, r1ou = FALSE;
163 /* the logic: if r0 & r1 used in the instruction
164 then we are in trouble otherwise */
166 /* first check if r0 & r1 are used by this
167 instruction, in which case we are in trouble */
168 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
169 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
174 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
175 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
177 /* if no usage of r0 then return it */
180 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
181 (*aopp)->type = AOP_R0;
183 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
186 /* if no usage of r1 then return it */
189 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
190 (*aopp)->type = AOP_R1;
192 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
195 /* now we know they both have usage */
196 /* if r0 not used in this instruction */
199 /* push it if not already pushed */
202 emitcode ("push", "%s",
203 mcs51_regWithIdx (R0_IDX)->dname);
207 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
208 (*aopp)->type = AOP_R0;
210 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
213 /* if r1 not used then */
217 /* push it if not already pushed */
220 emitcode ("push", "%s",
221 mcs51_regWithIdx (R1_IDX)->dname);
225 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
226 (*aopp)->type = AOP_R1;
227 return mcs51_regWithIdx (R1_IDX);
231 /* I said end of world but not quite end of world yet */
232 /* if this is a result then we can push it on the stack */
235 (*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));
258 /*-----------------------------------------------------------------*/
259 /* pointerCode - returns the code for a pointer type */
260 /*-----------------------------------------------------------------*/
262 pointerCode (sym_link * etype)
265 return PTR_TYPE (SPEC_OCLS (etype));
269 /*-----------------------------------------------------------------*/
270 /* aopForSym - for a true symbol */
271 /*-----------------------------------------------------------------*/
273 aopForSym (iCode * ic, symbol * sym, bool result)
278 wassertl (ic != NULL, "Got a null iCode");
279 wassertl (sym != NULL, "Got a null symbol");
281 space = SPEC_OCLS (sym->etype);
283 /* if already has one */
287 /* assign depending on the storage class */
288 /* if it is on the stack or indirectly addressable */
289 /* space we need to assign either r0 or r1 to it */
290 if (sym->onStack || sym->iaccess)
292 sym->aop = aop = newAsmop (0);
293 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
294 aop->size = getSize (sym->type);
296 /* now assign the address of the variable to
297 the pointer register */
298 if (aop->type != AOP_STK)
304 emitcode ("push", "acc");
306 emitcode ("mov", "a,_bp");
307 emitcode ("add", "a,#0x%02x",
309 ((char) (sym->stack - _G.nRegsSaved)) :
310 ((char) sym->stack)) & 0xff);
311 emitcode ("mov", "%s,a",
312 aop->aopu.aop_ptr->name);
315 emitcode ("pop", "acc");
318 emitcode ("mov", "%s,#%s",
319 aop->aopu.aop_ptr->name,
321 aop->paged = space->paged;
324 aop->aopu.aop_stk = sym->stack;
328 /* if in bit space */
329 if (IN_BITSPACE (space))
331 sym->aop = aop = newAsmop (AOP_CRY);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
336 /* if it is in direct space */
337 if (IN_DIRSPACE (space))
339 sym->aop = aop = newAsmop (AOP_DIR);
340 aop->aopu.aop_dir = sym->rname;
341 aop->size = getSize (sym->type);
345 /* special case for a function */
346 if (IS_FUNC (sym->type))
348 sym->aop = aop = newAsmop (AOP_IMMD);
349 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
350 strcpy (aop->aopu.aop_immd, sym->rname);
351 aop->size = FPTRSIZE;
355 /* only remaining is far space */
356 /* in which case DPTR gets the address */
357 sym->aop = aop = newAsmop (AOP_DPTR);
358 emitcode ("mov", "dptr,#%s", sym->rname);
359 aop->size = getSize (sym->type);
361 /* if it is in code space */
362 if (IN_CODESPACE (space))
368 /*-----------------------------------------------------------------*/
369 /* aopForRemat - rematerialzes an object */
370 /*-----------------------------------------------------------------*/
372 aopForRemat (symbol * sym)
374 iCode *ic = sym->rematiCode;
375 asmop *aop = newAsmop (AOP_IMMD);
381 val += (int) operandLitValue (IC_RIGHT (ic));
382 else if (ic->op == '-')
383 val -= (int) operandLitValue (IC_RIGHT (ic));
387 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
391 sprintf (buffer, "(%s %c 0x%04x)",
392 OP_SYMBOL (IC_LEFT (ic))->rname,
393 val >= 0 ? '+' : '-',
396 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
398 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
399 strcpy (aop->aopu.aop_immd, buffer);
403 /*-----------------------------------------------------------------*/
404 /* regsInCommon - two operands have some registers in common */
405 /*-----------------------------------------------------------------*/
407 regsInCommon (operand * op1, operand * op2)
412 /* if they have registers in common */
413 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
416 sym1 = OP_SYMBOL (op1);
417 sym2 = OP_SYMBOL (op2);
419 if (sym1->nRegs == 0 || sym2->nRegs == 0)
422 for (i = 0; i < sym1->nRegs; i++)
428 for (j = 0; j < sym2->nRegs; j++)
433 if (sym2->regs[j] == sym1->regs[i])
441 /*-----------------------------------------------------------------*/
442 /* operandsEqu - equivalent */
443 /*-----------------------------------------------------------------*/
445 operandsEqu (operand * op1, operand * op2)
449 /* if they not symbols */
450 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
453 sym1 = OP_SYMBOL (op1);
454 sym2 = OP_SYMBOL (op2);
456 /* if both are itemps & one is spilt
457 and the other is not then false */
458 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
459 sym1->isspilt != sym2->isspilt)
462 /* if they are the same */
466 if (strcmp (sym1->rname, sym2->rname) == 0)
470 /* if left is a tmp & right is not */
471 if (IS_ITEMP (op1) &&
474 (sym1->usl.spillLoc == sym2))
477 if (IS_ITEMP (op2) &&
481 (sym2->usl.spillLoc == sym1))
487 /*-----------------------------------------------------------------*/
488 /* sameRegs - two asmops have the same registers */
489 /*-----------------------------------------------------------------*/
491 sameRegs (asmop * aop1, asmop * aop2)
498 if (aop1->type != AOP_REG ||
499 aop2->type != AOP_REG)
502 if (aop1->size != aop2->size)
505 for (i = 0; i < aop1->size; i++)
506 if (aop1->aopu.aop_reg[i] !=
507 aop2->aopu.aop_reg[i])
513 /*-----------------------------------------------------------------*/
514 /* aopOp - allocates an asmop for an operand : */
515 /*-----------------------------------------------------------------*/
517 aopOp (operand * op, iCode * ic, bool result)
526 /* if this a literal */
527 if (IS_OP_LITERAL (op))
529 op->aop = aop = newAsmop (AOP_LIT);
530 aop->aopu.aop_lit = op->operand.valOperand;
531 aop->size = getSize (operandType (op));
535 /* if already has a asmop then continue */
539 /* if the underlying symbol has a aop */
540 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
542 op->aop = OP_SYMBOL (op)->aop;
546 /* if this is a true symbol */
547 if (IS_TRUE_SYMOP (op))
549 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
553 /* this is a temporary : this has
559 e) can be a return use only */
561 sym = OP_SYMBOL (op);
563 /* if the type is a conditional */
564 if (sym->regType == REG_CND)
566 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
571 /* if it is spilt then two situations
573 b) has a spill location */
574 if (sym->isspilt || sym->nRegs == 0)
577 /* rematerialize it NOW */
580 sym->aop = op->aop = aop =
582 aop->size = getSize (sym->type);
589 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
590 aop->size = getSize (sym->type);
591 for (i = 0; i < 2; i++)
592 aop->aopu.aop_str[i] = accUse[i];
600 aop = op->aop = sym->aop = newAsmop (AOP_STR);
601 aop->size = getSize (sym->type);
602 for (i = 0; i < fReturnSizeMCS51; i++)
603 aop->aopu.aop_str[i] = fReturn[i];
607 /* else spill location */
608 sym->aop = op->aop = aop =
609 aopForSym (ic, sym->usl.spillLoc, result);
610 aop->size = getSize (sym->type);
614 /* must be in a register */
615 sym->aop = op->aop = aop = newAsmop (AOP_REG);
616 aop->size = sym->nRegs;
617 for (i = 0; i < sym->nRegs; i++)
618 aop->aopu.aop_reg[i] = sym->regs[i];
621 /*-----------------------------------------------------------------*/
622 /* freeAsmop - free up the asmop given to an operand */
623 /*----------------------------------------------------------------*/
625 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
642 /* depending on the asmop type only three cases need work AOP_RO
643 , AOP_R1 && AOP_STK */
651 emitcode ("pop", "ar0");
655 bitVectUnSetBit (ic->rUsed, R0_IDX);
663 emitcode ("pop", "ar1");
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
673 int stk = aop->aopu.aop_stk + aop->size;
674 bitVectUnSetBit (ic->rUsed, R0_IDX);
675 bitVectUnSetBit (ic->rUsed, R1_IDX);
677 getFreePtr (ic, &aop, FALSE);
681 emitcode ("mov", "a,_bp");
682 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
683 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
687 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
692 emitcode ("pop", "acc");
693 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
696 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
699 freeAsmop (op, NULL, ic, TRUE);
702 emitcode ("pop", "ar0");
708 emitcode ("pop", "ar1");
715 /* all other cases just dealloc */
721 OP_SYMBOL (op)->aop = NULL;
722 /* if the symbol has a spill */
724 SPIL_LOC (op)->aop = NULL;
729 /*-----------------------------------------------------------------*/
730 /* aopGet - for fetching value of the aop */
731 /*-----------------------------------------------------------------*/
733 aopGet (asmop * aop, int offset, bool bit16, bool dname)
738 /* offset is greater than
740 if (offset > (aop->size - 1) &&
741 aop->type != AOP_LIT)
744 /* depending on type */
750 /* if we need to increment it */
751 while (offset > aop->coff)
753 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
757 while (offset < aop->coff)
759 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
766 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
767 return (dname ? "acc" : "a");
769 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
770 rs = Safe_calloc (1, strlen (s) + 1);
775 while (offset > aop->coff)
777 emitcode ("inc", "dptr");
781 while (offset < aop->coff)
783 emitcode ("lcall", "__decdptr");
790 emitcode ("clr", "a");
791 emitcode ("movc", "a,@a+dptr");
795 emitcode ("movx", "a,@dptr");
797 return (dname ? "acc" : "a");
802 sprintf (s, "#%s", aop->aopu.aop_immd);
804 sprintf (s, "#(%s >> %d)",
810 rs = Safe_calloc (1, strlen (s) + 1);
816 sprintf (s, "(%s + %d)",
820 sprintf (s, "%s", aop->aopu.aop_dir);
821 rs = Safe_calloc (1, strlen (s) + 1);
827 return aop->aopu.aop_reg[offset]->dname;
829 return aop->aopu.aop_reg[offset]->name;
832 emitcode ("clr", "a");
833 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
834 emitcode ("rlc", "a");
835 return (dname ? "acc" : "a");
838 if (!offset && dname)
840 return aop->aopu.aop_str[offset];
843 return aopLiteral (aop->aopu.aop_lit, offset);
847 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
851 return aop->aopu.aop_str[offset];
855 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
856 "aopget got unsupported aop->type");
859 /*-----------------------------------------------------------------*/
860 /* aopPut - puts a string for a aop */
861 /*-----------------------------------------------------------------*/
863 aopPut (asmop * aop, char *s, int offset)
867 if (aop->size && offset > (aop->size - 1))
869 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
870 "aopPut got offset > aop->size");
874 /* will assign value to value */
875 /* depending on where it is ofcourse */
880 sprintf (d, "(%s + %d)",
881 aop->aopu.aop_dir, offset);
883 sprintf (d, "%s", aop->aopu.aop_dir);
886 emitcode ("mov", "%s,%s", d, s);
891 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
892 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
895 strcmp (s, "r0") == 0 ||
896 strcmp (s, "r1") == 0 ||
897 strcmp (s, "r2") == 0 ||
898 strcmp (s, "r3") == 0 ||
899 strcmp (s, "r4") == 0 ||
900 strcmp (s, "r5") == 0 ||
901 strcmp (s, "r6") == 0 ||
902 strcmp (s, "r7") == 0)
903 emitcode ("mov", "%s,%s",
904 aop->aopu.aop_reg[offset]->dname, s);
906 emitcode ("mov", "%s,%s",
907 aop->aopu.aop_reg[offset]->name, s);
914 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
915 "aopPut writting to code space");
919 while (offset > aop->coff)
922 emitcode ("inc", "dptr");
925 while (offset < aop->coff)
928 emitcode ("lcall", "__decdptr");
933 /* if not in accumulater */
936 emitcode ("movx", "@dptr,a");
941 while (offset > aop->coff)
944 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
946 while (offset < aop->coff)
949 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
956 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
962 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
964 else if (strcmp (s, "r0") == 0 ||
965 strcmp (s, "r1") == 0 ||
966 strcmp (s, "r2") == 0 ||
967 strcmp (s, "r3") == 0 ||
968 strcmp (s, "r4") == 0 ||
969 strcmp (s, "r5") == 0 ||
970 strcmp (s, "r6") == 0 ||
971 strcmp (s, "r7") == 0)
974 sprintf (buffer, "a%s", s);
975 emitcode ("mov", "@%s,%s",
976 aop->aopu.aop_ptr->name, buffer);
979 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
984 if (strcmp (s, "a") == 0)
985 emitcode ("push", "acc");
987 emitcode ("push", "%s", s);
992 /* if bit variable */
993 if (!aop->aopu.aop_dir)
995 emitcode ("clr", "a");
996 emitcode ("rlc", "a");
1001 emitcode ("clr", "%s", aop->aopu.aop_dir);
1003 emitcode ("setb", "%s", aop->aopu.aop_dir);
1004 else if (!strcmp (s, "c"))
1005 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1008 if (strcmp (s, "a"))
1013 symbol *lbl = newiTempLabel (NULL);
1014 emitcode ("clr", "c");
1015 emitcode ("jz", "%05d$", lbl->key + 100);
1016 emitcode ("cpl", "c");
1017 emitcode ("", "%05d$:", lbl->key + 100);
1018 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1026 if (strcmp (aop->aopu.aop_str[offset], s))
1027 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 if (!offset && (strcmp (s, "acc") == 0))
1035 if (strcmp (aop->aopu.aop_str[offset], s))
1036 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1040 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1041 "aopPut got unsupported aop->type");
1049 /*-----------------------------------------------------------------*/
1050 /* pointToEnd :- points to the last byte of the operand */
1051 /*-----------------------------------------------------------------*/
1053 pointToEnd (asmop * aop)
1059 aop->coff = count = (aop->size - 1);
1065 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1069 emitcode ("inc", "dptr");
1076 /*-----------------------------------------------------------------*/
1077 /* reAdjustPreg - points a register back to where it should */
1078 /*-----------------------------------------------------------------*/
1080 reAdjustPreg (asmop * aop)
1082 if ((aop->coff==0) || aop->size <= 1)
1090 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1095 emitcode ("lcall", "__decdptr");
1102 #define AOP(op) op->aop
1103 #define AOP_TYPE(op) AOP(op)->type
1104 #define AOP_SIZE(op) AOP(op)->size
1105 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1106 AOP_TYPE(x) == AOP_R0))
1108 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1109 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1111 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1112 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1113 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1115 /*-----------------------------------------------------------------*/
1116 /* genNotFloat - generates not for float operations */
1117 /*-----------------------------------------------------------------*/
1119 genNotFloat (operand * op, operand * res)
1125 /* we will put 127 in the first byte of
1127 aopPut (AOP (res), "#127", 0);
1128 size = AOP_SIZE (op) - 1;
1131 l = aopGet (op->aop, offset++, FALSE, FALSE);
1136 emitcode ("orl", "a,%s",
1138 offset++, FALSE, FALSE));
1141 tlbl = newiTempLabel (NULL);
1142 aopPut (res->aop, one, 1);
1143 emitcode ("jz", "%05d$", (tlbl->key + 100));
1144 aopPut (res->aop, zero, 1);
1145 emitcode ("", "%05d$:", (tlbl->key + 100));
1147 size = res->aop->size - 2;
1149 /* put zeros in the rest */
1151 aopPut (res->aop, zero, offset++);
1154 /*-----------------------------------------------------------------*/
1155 /* opIsGptr: returns non-zero if the passed operand is */
1156 /* a generic pointer type. */
1157 /*-----------------------------------------------------------------*/
1159 opIsGptr (operand * op)
1161 sym_link *type = operandType (op);
1163 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1170 /*-----------------------------------------------------------------*/
1171 /* getDataSize - get the operand data size */
1172 /*-----------------------------------------------------------------*/
1174 getDataSize (operand * op)
1177 size = AOP_SIZE (op);
1178 if (size == GPTRSIZE)
1180 sym_link *type = operandType (op);
1181 if (IS_GENPTR (type))
1183 /* generic pointer; arithmetic operations
1184 * should ignore the high byte (pointer type).
1192 /*-----------------------------------------------------------------*/
1193 /* outAcc - output Acc */
1194 /*-----------------------------------------------------------------*/
1196 outAcc (operand * result)
1199 size = getDataSize (result);
1202 aopPut (AOP (result), "a", 0);
1205 /* unsigned or positive */
1208 aopPut (AOP (result), zero, offset++);
1213 /*-----------------------------------------------------------------*/
1214 /* outBitC - output a bit C */
1215 /*-----------------------------------------------------------------*/
1217 outBitC (operand * result)
1219 /* if the result is bit */
1220 if (AOP_TYPE (result) == AOP_CRY)
1221 aopPut (AOP (result), "c", 0);
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 /*-----------------------------------------------------------------*/
1231 /* toBoolean - emit code for orl a,operator(sizeop) */
1232 /*-----------------------------------------------------------------*/
1234 toBoolean (operand * oper)
1236 int size = AOP_SIZE (oper) - 1;
1238 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1240 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1244 /*-----------------------------------------------------------------*/
1245 /* genNot - generate code for ! operation */
1246 /*-----------------------------------------------------------------*/
1251 sym_link *optype = operandType (IC_LEFT (ic));
1253 /* assign asmOps to operand & result */
1254 aopOp (IC_LEFT (ic), ic, FALSE);
1255 aopOp (IC_RESULT (ic), ic, TRUE);
1257 /* if in bit space then a special case */
1258 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1260 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1261 emitcode ("cpl", "c");
1262 outBitC (IC_RESULT (ic));
1266 /* if type float then do float */
1267 if (IS_FLOAT (optype))
1269 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1273 toBoolean (IC_LEFT (ic));
1275 tlbl = newiTempLabel (NULL);
1276 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1277 emitcode ("", "%05d$:", tlbl->key + 100);
1278 outBitC (IC_RESULT (ic));
1281 /* release the aops */
1282 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1287 /*-----------------------------------------------------------------*/
1288 /* genCpl - generate code for complement */
1289 /*-----------------------------------------------------------------*/
1297 /* assign asmOps to operand & result */
1298 aopOp (IC_LEFT (ic), ic, FALSE);
1299 aopOp (IC_RESULT (ic), ic, TRUE);
1301 /* if both are in bit space then
1303 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1304 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1307 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1308 emitcode ("cpl", "c");
1309 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1313 size = AOP_SIZE (IC_RESULT (ic));
1316 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1318 emitcode ("cpl", "a");
1319 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1324 /* release the aops */
1325 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1329 /*-----------------------------------------------------------------*/
1330 /* genUminusFloat - unary minus for floating points */
1331 /*-----------------------------------------------------------------*/
1333 genUminusFloat (operand * op, operand * result)
1335 int size, offset = 0;
1337 /* for this we just need to flip the
1338 first it then copy the rest in place */
1339 size = AOP_SIZE (op) - 1;
1340 l = aopGet (AOP (op), 3, FALSE, FALSE);
1344 emitcode ("cpl", "acc.7");
1345 aopPut (AOP (result), "a", 3);
1349 aopPut (AOP (result),
1350 aopGet (AOP (op), offset, FALSE, FALSE),
1356 /*-----------------------------------------------------------------*/
1357 /* genUminus - unary minus code generation */
1358 /*-----------------------------------------------------------------*/
1360 genUminus (iCode * ic)
1363 sym_link *optype, *rtype;
1367 aopOp (IC_LEFT (ic), ic, FALSE);
1368 aopOp (IC_RESULT (ic), ic, TRUE);
1370 /* if both in bit space then special
1372 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1373 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1376 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1377 emitcode ("cpl", "c");
1378 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1382 optype = operandType (IC_LEFT (ic));
1383 rtype = operandType (IC_RESULT (ic));
1385 /* if float then do float stuff */
1386 if (IS_FLOAT (optype))
1388 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1392 /* otherwise subtract from zero */
1393 size = AOP_SIZE (IC_LEFT (ic));
1398 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1399 if (!strcmp (l, "a"))
1403 emitcode ("cpl", "a");
1404 emitcode ("addc", "a,#0");
1410 emitcode ("clr", "a");
1411 emitcode ("subb", "a,%s", l);
1413 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1416 /* if any remaining bytes in the result */
1417 /* we just need to propagate the sign */
1418 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1420 emitcode ("rlc", "a");
1421 emitcode ("subb", "a,acc");
1423 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1427 /* release the aops */
1428 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1429 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1432 /*-----------------------------------------------------------------*/
1433 /* saveRegisters - will look for a call and save the registers */
1434 /*-----------------------------------------------------------------*/
1436 saveRegisters (iCode * lic)
1444 for (ic = lic; ic; ic = ic->next)
1445 if (ic->op == CALL || ic->op == PCALL)
1450 fprintf (stderr, "found parameter push with no function call\n");
1454 /* if the registers have been saved already or don't need to be then
1456 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1457 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1460 /* find the registers in use at this time
1461 and push them away to safety */
1462 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1466 if (options.useXstack)
1468 if (bitVectBitValue (rsave, R0_IDX))
1469 emitcode ("mov", "b,r0");
1470 emitcode ("mov", "r0,%s", spname);
1471 for (i = 0; i < mcs51_nRegs; i++)
1473 if (bitVectBitValue (rsave, i))
1476 emitcode ("mov", "a,b");
1478 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1479 emitcode ("movx", "@r0,a");
1480 emitcode ("inc", "r0");
1483 emitcode ("mov", "%s,r0", spname);
1484 if (bitVectBitValue (rsave, R0_IDX))
1485 emitcode ("mov", "r0,b");
1488 for (i = 0; i < mcs51_nRegs; i++)
1490 if (bitVectBitValue (rsave, i))
1491 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1494 detype = getSpec (operandType (IC_LEFT (ic)));
1497 /*-----------------------------------------------------------------*/
1498 /* unsaveRegisters - pop the pushed registers */
1499 /*-----------------------------------------------------------------*/
1501 unsaveRegisters (iCode * ic)
1505 /* find the registers in use at this time
1506 and push them away to safety */
1507 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1510 if (options.useXstack)
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = mcs51_nRegs; i >= 0; i--)
1515 if (bitVectBitValue (rsave, i))
1517 emitcode ("dec", "r0");
1518 emitcode ("movx", "a,@r0");
1520 emitcode ("mov", "b,a");
1522 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1526 emitcode ("mov", "%s,r0", spname);
1527 if (bitVectBitValue (rsave, R0_IDX))
1528 emitcode ("mov", "r0,b");
1531 for (i = mcs51_nRegs; i >= 0; i--)
1533 if (bitVectBitValue (rsave, i))
1534 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1540 /*-----------------------------------------------------------------*/
1542 /*-----------------------------------------------------------------*/
1544 pushSide (operand * oper, int size)
1549 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1550 if (AOP_TYPE (oper) != AOP_REG &&
1551 AOP_TYPE (oper) != AOP_DIR &&
1554 emitcode ("mov", "a,%s", l);
1555 emitcode ("push", "acc");
1558 emitcode ("push", "%s", l);
1562 /*-----------------------------------------------------------------*/
1563 /* assignResultValue - */
1564 /*-----------------------------------------------------------------*/
1566 assignResultValue (operand * oper)
1569 int size = AOP_SIZE (oper);
1572 aopPut (AOP (oper), fReturn[offset], offset);
1578 /*-----------------------------------------------------------------*/
1579 /* genXpush - pushes onto the external stack */
1580 /*-----------------------------------------------------------------*/
1582 genXpush (iCode * ic)
1584 asmop *aop = newAsmop (0);
1586 int size, offset = 0;
1588 aopOp (IC_LEFT (ic), ic, FALSE);
1589 r = getFreePtr (ic, &aop, FALSE);
1592 emitcode ("mov", "%s,_spx", r->name);
1594 size = AOP_SIZE (IC_LEFT (ic));
1598 char *l = aopGet (AOP (IC_LEFT (ic)),
1599 offset++, FALSE, FALSE);
1601 emitcode ("movx", "@%s,a", r->name);
1602 emitcode ("inc", "%s", r->name);
1607 emitcode ("mov", "_spx,%s", r->name);
1609 freeAsmop (NULL, aop, ic, TRUE);
1610 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* genIpush - genrate code for pushing this gets a little complex */
1615 /*-----------------------------------------------------------------*/
1617 genIpush (iCode * ic)
1619 int size, offset = 0;
1622 D(emitcode (";", "genIpush"));
1624 /* if this is not a parm push : ie. it is spill push
1625 and spill push is always done on the local stack */
1629 /* and the item is spilt then do nothing */
1630 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1633 aopOp (IC_LEFT (ic), ic, FALSE);
1634 size = AOP_SIZE (IC_LEFT (ic));
1635 /* push it on the stack */
1638 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1644 emitcode ("push", "%s", l);
1649 /* this is a paramter push: in this case we call
1650 the routine to find the call and save those
1651 registers that need to be saved */
1654 /* if use external stack then call the external
1655 stack pushing routine */
1656 if (options.useXstack)
1662 /* then do the push */
1663 aopOp (IC_LEFT (ic), ic, FALSE);
1666 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1667 size = AOP_SIZE (IC_LEFT (ic));
1671 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1672 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1673 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1676 emitcode ("mov", "a,%s", l);
1677 emitcode ("push", "acc");
1680 emitcode ("push", "%s", l);
1683 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1686 /*-----------------------------------------------------------------*/
1687 /* genIpop - recover the registers: can happen only for spilling */
1688 /*-----------------------------------------------------------------*/
1690 genIpop (iCode * ic)
1695 /* if the temp was not pushed then */
1696 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1699 aopOp (IC_LEFT (ic), ic, FALSE);
1700 size = AOP_SIZE (IC_LEFT (ic));
1701 offset = (size - 1);
1703 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1709 /*-----------------------------------------------------------------*/
1710 /* unsaveRBank - restores the resgister bank from stack */
1711 /*-----------------------------------------------------------------*/
1713 unsaveRBank (int bank, iCode * ic, bool popPsw)
1719 if (options.useXstack)
1723 /* Assume r0 is available for use. */
1724 r = mcs51_regWithIdx (R0_IDX);;
1729 r = getFreePtr (ic, &aop, FALSE);
1731 emitcode ("mov", "%s,_spx", r->name);
1736 if (options.useXstack)
1738 emitcode ("movx", "a,@%s", r->name);
1739 emitcode ("mov", "psw,a");
1740 emitcode ("dec", "%s", r->name);
1744 emitcode ("pop", "psw");
1748 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1750 if (options.useXstack)
1752 emitcode ("movx", "a,@%s", r->name);
1753 emitcode ("mov", "(%s+%d),a",
1754 regs8051[i].base, 8 * bank + regs8051[i].offset);
1755 emitcode ("dec", "%s", r->name);
1759 emitcode ("pop", "(%s+%d)",
1760 regs8051[i].base, 8 * bank + regs8051[i].offset);
1763 if (options.useXstack)
1765 emitcode ("mov", "_spx,%s", r->name);
1770 freeAsmop (NULL, aop, ic, TRUE);
1774 /*-----------------------------------------------------------------*/
1775 /* saveRBank - saves an entire register bank on the stack */
1776 /*-----------------------------------------------------------------*/
1778 saveRBank (int bank, iCode * ic, bool pushPsw)
1784 if (options.useXstack)
1788 /* Assume r0 is available for use. */
1789 r = mcs51_regWithIdx (R0_IDX);;
1794 r = getFreePtr (ic, &aop, FALSE);
1796 emitcode ("mov", "%s,_spx", r->name);
1799 for (i = 0; i < mcs51_nRegs; i++)
1801 if (options.useXstack)
1803 emitcode ("inc", "%s", r->name);
1804 emitcode ("mov", "a,(%s+%d)",
1805 regs8051[i].base, 8 * bank + regs8051[i].offset);
1806 emitcode ("movx", "@%s,a", r->name);
1809 emitcode ("push", "(%s+%d)",
1810 regs8051[i].base, 8 * bank + regs8051[i].offset);
1815 if (options.useXstack)
1817 emitcode ("mov", "a,psw");
1818 emitcode ("movx", "@%s,a", r->name);
1819 emitcode ("inc", "%s", r->name);
1820 emitcode ("mov", "_spx,%s", r->name);
1825 emitcode ("push", "psw");
1828 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1833 freeAsmop (NULL, aop, ic, TRUE);
1842 /*-----------------------------------------------------------------*/
1843 /* genCall - generates a call statement */
1844 /*-----------------------------------------------------------------*/
1846 genCall (iCode * ic)
1849 bool restoreBank = FALSE;
1850 bool swapBanks = FALSE;
1852 D(emitcode(";", "genCall"));
1853 /* if send set is not empty the assign */
1858 for (sic = setFirstItem (_G.sendSet); sic;
1859 sic = setNextItem (_G.sendSet))
1861 int size, offset = 0;
1862 if (IS_VALOP(IC_LEFT(sic)) && IS_OP_LITERAL(IC_LEFT(sic))
1863 // PENDING: checkConstant2Type()
1864 // do some range checking here, just bitvars for now
1865 && IS_BITVAR(IC_LEFT(sic)->operand.valOperand->type)) {
1866 if (floatFromVal(IC_LEFT(sic)->operand.valOperand)) {
1867 emitcode ("mov", "%s,#0x01", fReturn[0]);
1869 emitcode ("mov", "%s,#0x00", fReturn[0]);
1872 aopOp (IC_LEFT (sic), sic, FALSE);
1873 size = AOP_SIZE (IC_LEFT (sic));
1876 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1878 if (strcmp (l, fReturn[offset]))
1879 emitcode ("mov", "%s,%s",
1884 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1890 /* if we are calling a not _naked function that is not using
1891 the same register bank then we need to save the
1892 destination registers on the stack */
1893 detype = getSpec (operandType (IC_LEFT (ic)));
1894 if (detype && !SPEC_NAKED(detype) &&
1895 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1896 IS_ISR (currFunc->etype))
1900 /* This is unexpected; the bank should have been saved in
1903 saveRBank (SPEC_BANK (detype), ic, FALSE);
1909 /* if caller saves & we have not saved then */
1915 emitcode ("mov", "psw,#0x%02x",
1916 ((SPEC_BANK(detype)) << 3) & 0xff);
1920 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1921 OP_SYMBOL (IC_LEFT (ic))->rname :
1922 OP_SYMBOL (IC_LEFT (ic))->name));
1926 emitcode ("mov", "psw,#0x%02x",
1927 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1930 /* if we need assign a result value */
1931 if ((IS_ITEMP (IC_RESULT (ic)) &&
1932 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1933 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1934 IS_TRUE_SYMOP (IC_RESULT (ic)))
1938 aopOp (IC_RESULT (ic), ic, FALSE);
1941 assignResultValue (IC_RESULT (ic));
1943 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1946 /* adjust the stack for parameters if
1951 if (ic->parmBytes > 3)
1953 emitcode ("mov", "a,%s", spname);
1954 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1955 emitcode ("mov", "%s,a", spname);
1958 for (i = 0; i < ic->parmBytes; i++)
1959 emitcode ("dec", "%s", spname);
1962 /* if we hade saved some registers then unsave them */
1963 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1964 unsaveRegisters (ic);
1966 /* if register bank was saved then pop them */
1968 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1971 /*-----------------------------------------------------------------*/
1972 /* genPcall - generates a call by pointer statement */
1973 /*-----------------------------------------------------------------*/
1975 genPcall (iCode * ic)
1978 symbol *rlbl = newiTempLabel (NULL);
1981 /* if caller saves & we have not saved then */
1985 /* if we are calling a function that is not using
1986 the same register bank then we need to save the
1987 destination registers on the stack */
1988 detype = getSpec (operandType (IC_LEFT (ic)));
1990 IS_ISR (currFunc->etype) &&
1991 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1992 saveRBank (SPEC_BANK (detype), ic, TRUE);
1995 /* push the return address on to the stack */
1996 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1997 emitcode ("push", "acc");
1998 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1999 emitcode ("push", "acc");
2001 /* now push the calling address */
2002 aopOp (IC_LEFT (ic), ic, FALSE);
2004 pushSide (IC_LEFT (ic), FPTRSIZE);
2006 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2008 /* if send set is not empty the assign */
2013 for (sic = setFirstItem (_G.sendSet); sic;
2014 sic = setNextItem (_G.sendSet))
2016 int size, offset = 0;
2017 aopOp (IC_LEFT (sic), sic, FALSE);
2018 size = AOP_SIZE (IC_LEFT (sic));
2021 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2023 if (strcmp (l, fReturn[offset]))
2024 emitcode ("mov", "%s,%s",
2029 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2034 emitcode ("ret", "");
2035 emitcode ("", "%05d$:", (rlbl->key + 100));
2038 /* if we need assign a result value */
2039 if ((IS_ITEMP (IC_RESULT (ic)) &&
2040 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2041 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2042 IS_TRUE_SYMOP (IC_RESULT (ic)))
2046 aopOp (IC_RESULT (ic), ic, FALSE);
2049 assignResultValue (IC_RESULT (ic));
2051 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2054 /* adjust the stack for parameters if
2059 if (ic->parmBytes > 3)
2061 emitcode ("mov", "a,%s", spname);
2062 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2063 emitcode ("mov", "%s,a", spname);
2066 for (i = 0; i < ic->parmBytes; i++)
2067 emitcode ("dec", "%s", spname);
2071 /* if register bank was saved then unsave them */
2073 (SPEC_BANK (currFunc->etype) !=
2074 SPEC_BANK (detype)))
2075 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2077 /* if we hade saved some registers then
2080 unsaveRegisters (ic);
2084 /*-----------------------------------------------------------------*/
2085 /* resultRemat - result is rematerializable */
2086 /*-----------------------------------------------------------------*/
2088 resultRemat (iCode * ic)
2090 if (SKIP_IC (ic) || ic->op == IFX)
2093 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2095 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2096 if (sym->remat && !POINTER_SET (ic))
2103 #if defined(__BORLANDC__) || defined(_MSC_VER)
2104 #define STRCASECMP stricmp
2106 #define STRCASECMP strcasecmp
2109 /*-----------------------------------------------------------------*/
2110 /* inExcludeList - return 1 if the string is in exclude Reg list */
2111 /*-----------------------------------------------------------------*/
2113 inExcludeList (char *s)
2117 if (options.excludeRegs[i] &&
2118 STRCASECMP (options.excludeRegs[i], "none") == 0)
2121 for (i = 0; options.excludeRegs[i]; i++)
2123 if (options.excludeRegs[i] &&
2124 STRCASECMP (s, options.excludeRegs[i]) == 0)
2130 /*-----------------------------------------------------------------*/
2131 /* genFunction - generated code for function entry */
2132 /*-----------------------------------------------------------------*/
2134 genFunction (iCode * ic)
2138 bool switchedPSW = FALSE;
2141 /* create the function header */
2142 emitcode (";", "-----------------------------------------");
2143 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2144 emitcode (";", "-----------------------------------------");
2146 emitcode ("", "%s:", sym->rname);
2147 fetype = getSpec (operandType (IC_LEFT (ic)));
2149 if (SPEC_NAKED(fetype))
2151 emitcode(";", "naked function: no prologue.");
2155 /* if critical function then turn interrupts off */
2156 if (SPEC_CRTCL (fetype))
2157 emitcode ("clr", "ea");
2159 /* here we need to generate the equates for the
2160 register bank if required */
2161 if (SPEC_BANK (fetype) != rbank)
2165 rbank = SPEC_BANK (fetype);
2166 for (i = 0; i < mcs51_nRegs; i++)
2168 if (strcmp (regs8051[i].base, "0") == 0)
2169 emitcode ("", "%s = 0x%02x",
2171 8 * rbank + regs8051[i].offset);
2173 emitcode ("", "%s = %s + 0x%02x",
2176 8 * rbank + regs8051[i].offset);
2180 /* if this is an interrupt service routine then
2181 save acc, b, dpl, dph */
2182 if (IS_ISR (sym->etype))
2185 if (!inExcludeList ("acc"))
2186 emitcode ("push", "acc");
2187 if (!inExcludeList ("b"))
2188 emitcode ("push", "b");
2189 if (!inExcludeList ("dpl"))
2190 emitcode ("push", "dpl");
2191 if (!inExcludeList ("dph"))
2192 emitcode ("push", "dph");
2193 /* if this isr has no bank i.e. is going to
2194 run with bank 0 , then we need to save more
2196 if (!SPEC_BANK (sym->etype))
2199 /* if this function does not call any other
2200 function then we can be economical and
2201 save only those registers that are used */
2206 /* if any registers used */
2209 /* save the registers used */
2210 for (i = 0; i < sym->regsUsed->size; i++)
2212 if (bitVectBitValue (sym->regsUsed, i) ||
2213 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2214 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2221 /* this function has a function call cannot
2222 determines register usage so we will have to push the
2224 saveRBank (0, ic, FALSE);
2229 /* This ISR uses a non-zero bank.
2231 * We assume that the bank is available for our
2234 * However, if this ISR calls a function which uses some
2235 * other bank, we must save that bank entirely.
2237 unsigned long banksToSave = 0;
2242 #define MAX_REGISTER_BANKS 4
2247 for (i = ic; i; i = i->next)
2249 if (i->op == ENDFUNCTION)
2251 /* we got to the end OK. */
2259 detype = getSpec(operandType (IC_LEFT(i)));
2261 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2263 /* Mark this bank for saving. */
2264 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2266 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2270 banksToSave |= (1 << SPEC_BANK(detype));
2273 /* And note that we don't need to do it in
2281 /* This is a mess; we have no idea what
2282 * register bank the called function might
2285 * The only thing I can think of to do is
2286 * throw a warning and hope.
2288 werror(W_FUNCPTR_IN_USING_ISR);
2292 if (banksToSave && options.useXstack)
2294 /* Since we aren't passing it an ic,
2295 * saveRBank will assume r0 is available to abuse.
2297 * So switch to our (trashable) bank now, so
2298 * the caller's R0 isn't trashed.
2300 emitcode ("push", "psw");
2301 emitcode ("mov", "psw,#0x%02x",
2302 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2306 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2308 if (banksToSave & (1 << ix))
2310 saveRBank(ix, NULL, FALSE);
2314 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2319 /* if callee-save to be used for this function
2320 then save the registers being used in this function */
2321 if (sym->calleeSave)
2325 /* if any registers used */
2328 /* save the registers used */
2329 for (i = 0; i < sym->regsUsed->size; i++)
2331 if (bitVectBitValue (sym->regsUsed, i) ||
2332 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2334 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2342 /* set the register bank to the desired value */
2343 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2346 emitcode ("push", "psw");
2347 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2350 if (IS_RENT (sym->etype) || options.stackAuto)
2353 if (options.useXstack)
2355 emitcode ("mov", "r0,%s", spname);
2356 emitcode ("mov", "a,_bp");
2357 emitcode ("movx", "@r0,a");
2358 emitcode ("inc", "%s", spname);
2362 /* set up the stack */
2363 emitcode ("push", "_bp"); /* save the callers stack */
2365 emitcode ("mov", "_bp,%s", spname);
2368 /* adjust the stack for the function */
2374 werror (W_STACK_OVERFLOW, sym->name);
2376 if (i > 3 && sym->recvSize < 4)
2379 emitcode ("mov", "a,sp");
2380 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2381 emitcode ("mov", "sp,a");
2386 emitcode ("inc", "sp");
2392 emitcode ("mov", "a,_spx");
2393 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2394 emitcode ("mov", "_spx,a");
2399 /*-----------------------------------------------------------------*/
2400 /* genEndFunction - generates epilogue for functions */
2401 /*-----------------------------------------------------------------*/
2403 genEndFunction (iCode * ic)
2405 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2407 if (SPEC_NAKED(sym->etype))
2409 emitcode(";", "naked function: no epilogue.");
2413 if (IS_RENT (sym->etype) || options.stackAuto)
2415 emitcode ("mov", "%s,_bp", spname);
2418 /* if use external stack but some variables were
2419 added to the local stack then decrement the
2421 if (options.useXstack && sym->stack)
2423 emitcode ("mov", "a,sp");
2424 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2425 emitcode ("mov", "sp,a");
2429 if ((IS_RENT (sym->etype) || options.stackAuto))
2431 if (options.useXstack)
2433 emitcode ("mov", "r0,%s", spname);
2434 emitcode ("movx", "a,@r0");
2435 emitcode ("mov", "_bp,a");
2436 emitcode ("dec", "%s", spname);
2440 emitcode ("pop", "_bp");
2444 /* restore the register bank */
2445 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2447 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2448 || !options.useXstack)
2450 /* Special case of ISR using non-zero bank with useXstack
2453 emitcode ("pop", "psw");
2457 if (IS_ISR (sym->etype))
2460 /* now we need to restore the registers */
2461 /* if this isr has no bank i.e. is going to
2462 run with bank 0 , then we need to save more
2464 if (!SPEC_BANK (sym->etype))
2466 /* if this function does not call any other
2467 function then we can be economical and
2468 save only those registers that are used */
2473 /* if any registers used */
2476 /* save the registers used */
2477 for (i = sym->regsUsed->size; i >= 0; i--)
2479 if (bitVectBitValue (sym->regsUsed, i) ||
2480 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2481 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2488 /* this function has a function call cannot
2489 determines register usage so we will have to pop the
2491 unsaveRBank (0, ic, FALSE);
2496 /* This ISR uses a non-zero bank.
2498 * Restore any register banks saved by genFunction
2501 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2504 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2506 if (savedBanks & (1 << ix))
2508 unsaveRBank(ix, NULL, FALSE);
2512 if (options.useXstack)
2514 /* Restore bank AFTER calling unsaveRBank,
2515 * since it can trash r0.
2517 emitcode ("pop", "psw");
2521 if (!inExcludeList ("dph"))
2522 emitcode ("pop", "dph");
2523 if (!inExcludeList ("dpl"))
2524 emitcode ("pop", "dpl");
2525 if (!inExcludeList ("b"))
2526 emitcode ("pop", "b");
2527 if (!inExcludeList ("acc"))
2528 emitcode ("pop", "acc");
2530 if (SPEC_CRTCL (sym->etype))
2531 emitcode ("setb", "ea");
2533 /* if debug then send end of function */
2534 /* if (options.debug && currFunc) */
2535 if (options.debug && currFunc)
2538 emitcode ("", "C$%s$%d$%d$%d ==.",
2539 FileBaseName (ic->filename), currFunc->lastLine,
2540 ic->level, ic->block);
2541 if (IS_STATIC (currFunc->etype))
2542 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2544 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2548 emitcode ("reti", "");
2552 if (SPEC_CRTCL (sym->etype))
2553 emitcode ("setb", "ea");
2555 if (sym->calleeSave)
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = sym->regsUsed->size; i >= 0; i--)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2573 /* if debug then send end of function */
2574 if (options.debug && currFunc)
2577 emitcode ("", "C$%s$%d$%d$%d ==.",
2578 FileBaseName (ic->filename), currFunc->lastLine,
2579 ic->level, ic->block);
2580 if (IS_STATIC (currFunc->etype))
2581 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2583 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2587 emitcode ("ret", "");
2592 /*-----------------------------------------------------------------*/
2593 /* genRet - generate code for return statement */
2594 /*-----------------------------------------------------------------*/
2598 int size, offset = 0, pushed = 0;
2600 /* if we have no return value then
2601 just generate the "ret" */
2605 /* we have something to return then
2606 move the return value into place */
2607 aopOp (IC_LEFT (ic), ic, FALSE);
2608 size = AOP_SIZE (IC_LEFT (ic));
2613 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2616 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2618 emitcode ("push", "%s", l);
2623 l = aopGet (AOP (IC_LEFT (ic)), offset,
2625 if (strcmp (fReturn[offset], l))
2626 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2635 if (strcmp (fReturn[pushed], "a"))
2636 emitcode ("pop", fReturn[pushed]);
2638 emitcode ("pop", "acc");
2641 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2644 /* generate a jump to the return label
2645 if the next is not the return statement */
2646 if (!(ic->next && ic->next->op == LABEL &&
2647 IC_LABEL (ic->next) == returnLabel))
2649 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2653 /*-----------------------------------------------------------------*/
2654 /* genLabel - generates a label */
2655 /*-----------------------------------------------------------------*/
2657 genLabel (iCode * ic)
2659 /* special case never generate */
2660 if (IC_LABEL (ic) == entryLabel)
2663 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2666 /*-----------------------------------------------------------------*/
2667 /* genGoto - generates a ljmp */
2668 /*-----------------------------------------------------------------*/
2670 genGoto (iCode * ic)
2672 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2675 /*-----------------------------------------------------------------*/
2676 /* findLabelBackwards: walks back through the iCode chain looking */
2677 /* for the given label. Returns number of iCode instructions */
2678 /* between that label and given ic. */
2679 /* Returns zero if label not found. */
2680 /*-----------------------------------------------------------------*/
2682 findLabelBackwards (iCode * ic, int key)
2691 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2693 /* printf("findLabelBackwards = %d\n", count); */
2701 /*-----------------------------------------------------------------*/
2702 /* genPlusIncr :- does addition with increment if possible */
2703 /*-----------------------------------------------------------------*/
2705 genPlusIncr (iCode * ic)
2707 unsigned int icount;
2708 unsigned int size = getDataSize (IC_RESULT (ic));
2710 /* will try to generate an increment */
2711 /* if the right side is not a literal
2713 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2716 /* if the literal value of the right hand side
2717 is greater than 4 then it is not worth it */
2718 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2721 /* if increment 16 bits in register */
2722 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2730 /* If the next instruction is a goto and the goto target
2731 * is < 10 instructions previous to this, we can generate
2732 * jumps straight to that target.
2734 if (ic->next && ic->next->op == GOTO
2735 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2736 && labelRange <= 10)
2738 emitcode (";", "tail increment optimized");
2739 tlbl = IC_LABEL (ic->next);
2744 tlbl = newiTempLabel (NULL);
2747 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2748 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2749 IS_AOP_PREG (IC_RESULT (ic)))
2750 emitcode ("cjne", "%s,#0x00,%05d$"
2751 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2755 emitcode ("clr", "a");
2756 emitcode ("cjne", "a,%s,%05d$"
2757 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2761 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2764 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2765 IS_AOP_PREG (IC_RESULT (ic)))
2766 emitcode ("cjne", "%s,#0x00,%05d$"
2767 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2770 emitcode ("cjne", "a,%s,%05d$"
2771 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2774 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2778 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2779 IS_AOP_PREG (IC_RESULT (ic)))
2780 emitcode ("cjne", "%s,#0x00,%05d$"
2781 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2785 emitcode ("cjne", "a,%s,%05d$"
2786 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2789 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2794 emitcode ("", "%05d$:", tlbl->key + 100);
2799 /* if the sizes are greater than 1 then we cannot */
2800 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2801 AOP_SIZE (IC_LEFT (ic)) > 1)
2804 /* we can if the aops of the left & result match or
2805 if they are in registers and the registers are the
2807 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2812 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2813 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2814 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2820 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2829 /*-----------------------------------------------------------------*/
2830 /* outBitAcc - output a bit in acc */
2831 /*-----------------------------------------------------------------*/
2833 outBitAcc (operand * result)
2835 symbol *tlbl = newiTempLabel (NULL);
2836 /* if the result is a bit */
2837 if (AOP_TYPE (result) == AOP_CRY)
2839 aopPut (AOP (result), "a", 0);
2843 emitcode ("jz", "%05d$", tlbl->key + 100);
2844 emitcode ("mov", "a,%s", one);
2845 emitcode ("", "%05d$:", tlbl->key + 100);
2850 /*-----------------------------------------------------------------*/
2851 /* genPlusBits - generates code for addition of two bits */
2852 /*-----------------------------------------------------------------*/
2854 genPlusBits (iCode * ic)
2856 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2858 symbol *lbl = newiTempLabel (NULL);
2859 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2860 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2861 emitcode ("cpl", "c");
2862 emitcode ("", "%05d$:", (lbl->key + 100));
2863 outBitC (IC_RESULT (ic));
2867 emitcode ("clr", "a");
2868 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2869 emitcode ("rlc", "a");
2870 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2871 emitcode ("addc", "a,#0x00");
2872 outAcc (IC_RESULT (ic));
2877 /* This is the original version of this code.
2879 * This is being kept around for reference,
2880 * because I am not entirely sure I got it right...
2883 adjustArithmeticResult (iCode * ic)
2885 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2886 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2887 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2888 aopPut (AOP (IC_RESULT (ic)),
2889 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2892 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2893 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2894 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2895 aopPut (AOP (IC_RESULT (ic)),
2896 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2899 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2900 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2901 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2902 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2903 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2906 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2907 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2911 /* This is the pure and virtuous version of this code.
2912 * I'm pretty certain it's right, but not enough to toss the old
2916 adjustArithmeticResult (iCode * ic)
2918 if (opIsGptr (IC_RESULT (ic)) &&
2919 opIsGptr (IC_LEFT (ic)) &&
2920 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2922 aopPut (AOP (IC_RESULT (ic)),
2923 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2927 if (opIsGptr (IC_RESULT (ic)) &&
2928 opIsGptr (IC_RIGHT (ic)) &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2931 aopPut (AOP (IC_RESULT (ic)),
2932 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2936 if (opIsGptr (IC_RESULT (ic)) &&
2937 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2938 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2939 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2940 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2943 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2944 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2949 /*-----------------------------------------------------------------*/
2950 /* genPlus - generates code for addition */
2951 /*-----------------------------------------------------------------*/
2953 genPlus (iCode * ic)
2955 int size, offset = 0;
2957 /* special cases :- */
2959 aopOp (IC_LEFT (ic), ic, FALSE);
2960 aopOp (IC_RIGHT (ic), ic, FALSE);
2961 aopOp (IC_RESULT (ic), ic, TRUE);
2963 /* if literal, literal on the right or
2964 if left requires ACC or right is already
2966 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2967 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2968 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2970 operand *t = IC_RIGHT (ic);
2971 IC_RIGHT (ic) = IC_LEFT (ic);
2975 /* if both left & right are in bit
2977 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2978 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2984 /* if left in bit space & right literal */
2985 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2986 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2988 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2989 /* if result in bit space */
2990 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2992 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2993 emitcode ("cpl", "c");
2994 outBitC (IC_RESULT (ic));
2998 size = getDataSize (IC_RESULT (ic));
3001 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3002 emitcode ("addc", "a,#00");
3003 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3009 /* if I can do an increment instead
3010 of add then GOOD for ME */
3011 if (genPlusIncr (ic) == TRUE)
3014 size = getDataSize (IC_RESULT (ic));
3018 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3020 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3022 emitcode ("add", "a,%s",
3023 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3025 emitcode ("addc", "a,%s",
3026 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3030 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3032 emitcode ("add", "a,%s",
3033 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3035 emitcode ("addc", "a,%s",
3036 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3038 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3041 adjustArithmeticResult (ic);
3044 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3045 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3046 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3049 /*-----------------------------------------------------------------*/
3050 /* genMinusDec :- does subtraction with deccrement if possible */
3051 /*-----------------------------------------------------------------*/
3053 genMinusDec (iCode * ic)
3055 unsigned int icount;
3056 unsigned int size = getDataSize (IC_RESULT (ic));
3058 /* will try to generate an increment */
3059 /* if the right side is not a literal
3061 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3064 /* if the literal value of the right hand side
3065 is greater than 4 then it is not worth it */
3066 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3069 /* if decrement 16 bits in register */
3070 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3078 /* If the next instruction is a goto and the goto target
3079 * is <= 10 instructions previous to this, we can generate
3080 * jumps straight to that target.
3082 if (ic->next && ic->next->op == GOTO
3083 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3084 && labelRange <= 10)
3086 emitcode (";", "tail decrement optimized");
3087 tlbl = IC_LABEL (ic->next);
3092 tlbl = newiTempLabel (NULL);
3096 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3097 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3098 IS_AOP_PREG (IC_RESULT (ic)))
3099 emitcode ("cjne", "%s,#0xff,%05d$"
3100 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3104 emitcode ("mov", "a,#0xff");
3105 emitcode ("cjne", "a,%s,%05d$"
3106 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3109 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3112 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3113 IS_AOP_PREG (IC_RESULT (ic)))
3114 emitcode ("cjne", "%s,#0xff,%05d$"
3115 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3119 emitcode ("cjne", "a,%s,%05d$"
3120 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3123 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3127 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3128 IS_AOP_PREG (IC_RESULT (ic)))
3129 emitcode ("cjne", "%s,#0xff,%05d$"
3130 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3134 emitcode ("cjne", "a,%s,%05d$"
3135 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3138 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3142 emitcode ("", "%05d$:", tlbl->key + 100);
3147 /* if the sizes are greater than 1 then we cannot */
3148 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3149 AOP_SIZE (IC_LEFT (ic)) > 1)
3152 /* we can if the aops of the left & result match or
3153 if they are in registers and the registers are the
3155 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3159 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3167 /*-----------------------------------------------------------------*/
3168 /* addSign - complete with sign */
3169 /*-----------------------------------------------------------------*/
3171 addSign (operand * result, int offset, int sign)
3173 int size = (getDataSize (result) - offset);
3178 emitcode ("rlc", "a");
3179 emitcode ("subb", "a,acc");
3181 aopPut (AOP (result), "a", offset++);
3185 aopPut (AOP (result), zero, offset++);
3189 /*-----------------------------------------------------------------*/
3190 /* genMinusBits - generates code for subtraction of two bits */
3191 /*-----------------------------------------------------------------*/
3193 genMinusBits (iCode * ic)
3195 symbol *lbl = newiTempLabel (NULL);
3196 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3198 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3199 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3200 emitcode ("cpl", "c");
3201 emitcode ("", "%05d$:", (lbl->key + 100));
3202 outBitC (IC_RESULT (ic));
3206 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3207 emitcode ("subb", "a,acc");
3208 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3209 emitcode ("inc", "a");
3210 emitcode ("", "%05d$:", (lbl->key + 100));
3211 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3212 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3216 /*-----------------------------------------------------------------*/
3217 /* genMinus - generates code for subtraction */
3218 /*-----------------------------------------------------------------*/
3220 genMinus (iCode * ic)
3222 int size, offset = 0;
3223 unsigned long lit = 0L;
3225 aopOp (IC_LEFT (ic), ic, FALSE);
3226 aopOp (IC_RIGHT (ic), ic, FALSE);
3227 aopOp (IC_RESULT (ic), ic, TRUE);
3229 /* special cases :- */
3230 /* if both left & right are in bit space */
3231 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3232 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3238 /* if I can do an decrement instead
3239 of subtract then GOOD for ME */
3240 if (genMinusDec (ic) == TRUE)
3243 size = getDataSize (IC_RESULT (ic));
3245 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3251 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3255 /* if literal, add a,#-lit, else normal subb */
3258 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3259 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3260 emitcode ("subb", "a,%s",
3261 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3264 /* first add without previous c */
3266 if (!size && lit==-1) {
3267 emitcode ("dec", "a");
3269 emitcode ("add", "a,#0x%02x",
3270 (unsigned int) (lit & 0x0FFL));
3273 emitcode ("addc", "a,#0x%02x",
3274 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3277 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3280 adjustArithmeticResult (ic);
3283 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3284 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3285 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3289 /*-----------------------------------------------------------------*/
3290 /* genMultbits :- multiplication of bits */
3291 /*-----------------------------------------------------------------*/
3293 genMultbits (operand * left,
3297 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3298 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3303 /*-----------------------------------------------------------------*/
3304 /* genMultOneByte : 8*8=8/16 bit multiplication */
3305 /*-----------------------------------------------------------------*/
3307 genMultOneByte (operand * left,
3311 sym_link *opetype = operandType (result);
3313 int size=AOP_SIZE(result);
3315 if (size<1 || size>2) {
3316 // this should never happen
3317 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3318 AOP_SIZE(result), __FILE__, lineno);
3322 /* (if two literals: the value is computed before) */
3323 /* if one literal, literal on the right */
3324 if (AOP_TYPE (left) == AOP_LIT)
3329 //emitcode (";", "swapped left and right");
3332 if (SPEC_USIGN(opetype)
3333 // ignore the sign of left and right, what else can we do?
3334 || (SPEC_USIGN(operandType(left)) &&
3335 SPEC_USIGN(operandType(right)))) {
3336 // just an unsigned 8*8=8/16 multiply
3337 //emitcode (";","unsigned");
3338 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3339 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3340 emitcode ("mul", "ab");
3341 aopPut (AOP (result), "a", 0);
3343 aopPut (AOP (result), "b", 1);
3348 // we have to do a signed multiply
3350 //emitcode (";", "signed");
3351 emitcode ("clr", "F0"); // reset sign flag
3352 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3354 lbl=newiTempLabel(NULL);
3355 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3356 // left side is negative, 8-bit two's complement, this fails for -128
3357 emitcode ("setb", "F0"); // set sign flag
3358 emitcode ("cpl", "a");
3359 emitcode ("inc", "a");
3361 emitcode ("", "%05d$:", lbl->key+100);
3364 if (AOP_TYPE(right)==AOP_LIT) {
3365 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3366 /* AND literal negative */
3368 emitcode ("cpl", "F0"); // complement sign flag
3369 emitcode ("mov", "b,#0x%02x", -val);
3371 emitcode ("mov", "b,#0x%02x", val);
3374 lbl=newiTempLabel(NULL);
3375 emitcode ("mov", "b,a");
3376 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3377 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3378 // right side is negative, 8-bit two's complement
3379 emitcode ("cpl", "F0"); // complement sign flag
3380 emitcode ("cpl", "a");
3381 emitcode ("inc", "a");
3382 emitcode ("", "%05d$:", lbl->key+100);
3384 emitcode ("mul", "ab");
3386 lbl=newiTempLabel(NULL);
3387 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3388 // only ONE op was negative, we have to do a 8/16-bit two's complement
3389 emitcode ("cpl", "a"); // lsb
3391 emitcode ("inc", "a");
3393 emitcode ("add", "a,#1");
3394 emitcode ("xch", "a,b");
3395 emitcode ("cpl", "a"); // msb
3396 emitcode ("addc", "a,#0");
3397 emitcode ("xch", "a,b");
3400 emitcode ("", "%05d$:", lbl->key+100);
3401 aopPut (AOP (result), "a", 0);
3403 aopPut (AOP (result), "b", 1);
3407 /*-----------------------------------------------------------------*/
3408 /* genMult - generates code for multiplication */
3409 /*-----------------------------------------------------------------*/
3411 genMult (iCode * ic)
3413 operand *left = IC_LEFT (ic);
3414 operand *right = IC_RIGHT (ic);
3415 operand *result = IC_RESULT (ic);
3417 /* assign the amsops */
3418 aopOp (left, ic, FALSE);
3419 aopOp (right, ic, FALSE);
3420 aopOp (result, ic, TRUE);
3422 /* special cases first */
3424 if (AOP_TYPE (left) == AOP_CRY &&
3425 AOP_TYPE (right) == AOP_CRY)
3427 genMultbits (left, right, result);
3431 /* if both are of size == 1 */
3432 if (AOP_SIZE (left) == 1 &&
3433 AOP_SIZE (right) == 1)
3435 genMultOneByte (left, right, result);
3439 /* should have been converted to function call */
3443 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3445 freeAsmop (result, NULL, ic, TRUE);
3448 /*-----------------------------------------------------------------*/
3449 /* genDivbits :- division of bits */
3450 /*-----------------------------------------------------------------*/
3452 genDivbits (operand * left,
3459 /* the result must be bit */
3460 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3461 l = aopGet (AOP (left), 0, FALSE, FALSE);
3465 emitcode ("div", "ab");
3466 emitcode ("rrc", "a");
3467 aopPut (AOP (result), "c", 0);
3470 /*-----------------------------------------------------------------*/
3471 /* genDivOneByte : 8 bit division */
3472 /*-----------------------------------------------------------------*/
3474 genDivOneByte (operand * left,
3478 sym_link *opetype = operandType (result);
3483 size = AOP_SIZE (result) - 1;
3485 /* signed or unsigned */
3486 if (SPEC_USIGN (opetype))
3488 /* unsigned is easy */
3489 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3490 l = aopGet (AOP (left), 0, FALSE, FALSE);
3492 emitcode ("div", "ab");
3493 aopPut (AOP (result), "a", 0);
3495 aopPut (AOP (result), zero, offset++);
3499 /* signed is a little bit more difficult */
3501 /* save the signs of the operands */
3502 l = aopGet (AOP (left), 0, FALSE, FALSE);
3504 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3505 emitcode ("push", "acc"); /* save it on the stack */
3507 /* now sign adjust for both left & right */
3508 l = aopGet (AOP (right), 0, FALSE, FALSE);
3510 lbl = newiTempLabel (NULL);
3511 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3512 emitcode ("cpl", "a");
3513 emitcode ("inc", "a");
3514 emitcode ("", "%05d$:", (lbl->key + 100));
3515 emitcode ("mov", "b,a");
3517 /* sign adjust left side */
3518 l = aopGet (AOP (left), 0, FALSE, FALSE);
3521 lbl = newiTempLabel (NULL);
3522 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3523 emitcode ("cpl", "a");
3524 emitcode ("inc", "a");
3525 emitcode ("", "%05d$:", (lbl->key + 100));
3527 /* now the division */
3528 emitcode ("div", "ab");
3529 /* we are interested in the lower order
3531 emitcode ("mov", "b,a");
3532 lbl = newiTempLabel (NULL);
3533 emitcode ("pop", "acc");
3534 /* if there was an over flow we don't
3535 adjust the sign of the result */
3536 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3537 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3539 emitcode ("clr", "a");
3540 emitcode ("subb", "a,b");
3541 emitcode ("mov", "b,a");
3542 emitcode ("", "%05d$:", (lbl->key + 100));
3544 /* now we are done */
3545 aopPut (AOP (result), "b", 0);
3548 emitcode ("mov", "c,b.7");
3549 emitcode ("subb", "a,acc");
3552 aopPut (AOP (result), "a", offset++);
3556 /*-----------------------------------------------------------------*/
3557 /* genDiv - generates code for division */
3558 /*-----------------------------------------------------------------*/
3562 operand *left = IC_LEFT (ic);
3563 operand *right = IC_RIGHT (ic);
3564 operand *result = IC_RESULT (ic);
3566 /* assign the amsops */
3567 aopOp (left, ic, FALSE);
3568 aopOp (right, ic, FALSE);
3569 aopOp (result, ic, TRUE);
3571 /* special cases first */
3573 if (AOP_TYPE (left) == AOP_CRY &&
3574 AOP_TYPE (right) == AOP_CRY)
3576 genDivbits (left, right, result);
3580 /* if both are of size == 1 */
3581 if (AOP_SIZE (left) == 1 &&
3582 AOP_SIZE (right) == 1)
3584 genDivOneByte (left, right, result);
3588 /* should have been converted to function call */
3591 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3593 freeAsmop (result, NULL, ic, TRUE);
3596 /*-----------------------------------------------------------------*/
3597 /* genModbits :- modulus of bits */
3598 /*-----------------------------------------------------------------*/
3600 genModbits (operand * left,
3607 /* the result must be bit */
3608 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3609 l = aopGet (AOP (left), 0, FALSE, FALSE);
3613 emitcode ("div", "ab");
3614 emitcode ("mov", "a,b");
3615 emitcode ("rrc", "a");
3616 aopPut (AOP (result), "c", 0);
3619 /*-----------------------------------------------------------------*/
3620 /* genModOneByte : 8 bit modulus */
3621 /*-----------------------------------------------------------------*/
3623 genModOneByte (operand * left,
3627 sym_link *opetype = operandType (result);
3631 /* signed or unsigned */
3632 if (SPEC_USIGN (opetype))
3634 /* unsigned is easy */
3635 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3636 l = aopGet (AOP (left), 0, FALSE, FALSE);
3638 emitcode ("div", "ab");
3639 aopPut (AOP (result), "b", 0);
3643 /* signed is a little bit more difficult */
3645 /* save the signs of the operands */
3646 l = aopGet (AOP (left), 0, FALSE, FALSE);
3649 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3650 emitcode ("push", "acc"); /* save it on the stack */
3652 /* now sign adjust for both left & right */
3653 l = aopGet (AOP (right), 0, FALSE, FALSE);
3656 lbl = newiTempLabel (NULL);
3657 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3658 emitcode ("cpl", "a");
3659 emitcode ("inc", "a");
3660 emitcode ("", "%05d$:", (lbl->key + 100));
3661 emitcode ("mov", "b,a");
3663 /* sign adjust left side */
3664 l = aopGet (AOP (left), 0, FALSE, FALSE);
3667 lbl = newiTempLabel (NULL);
3668 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3669 emitcode ("cpl", "a");
3670 emitcode ("inc", "a");
3671 emitcode ("", "%05d$:", (lbl->key + 100));
3673 /* now the multiplication */
3674 emitcode ("div", "ab");
3675 /* we are interested in the lower order
3677 lbl = newiTempLabel (NULL);
3678 emitcode ("pop", "acc");
3679 /* if there was an over flow we don't
3680 adjust the sign of the result */
3681 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3682 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3684 emitcode ("clr", "a");
3685 emitcode ("subb", "a,b");
3686 emitcode ("mov", "b,a");
3687 emitcode ("", "%05d$:", (lbl->key + 100));
3689 /* now we are done */
3690 aopPut (AOP (result), "b", 0);
3694 /*-----------------------------------------------------------------*/
3695 /* genMod - generates code for division */
3696 /*-----------------------------------------------------------------*/
3700 operand *left = IC_LEFT (ic);
3701 operand *right = IC_RIGHT (ic);
3702 operand *result = IC_RESULT (ic);
3704 /* assign the amsops */
3705 aopOp (left, ic, FALSE);
3706 aopOp (right, ic, FALSE);
3707 aopOp (result, ic, TRUE);
3709 /* special cases first */
3711 if (AOP_TYPE (left) == AOP_CRY &&
3712 AOP_TYPE (right) == AOP_CRY)
3714 genModbits (left, right, result);
3718 /* if both are of size == 1 */
3719 if (AOP_SIZE (left) == 1 &&
3720 AOP_SIZE (right) == 1)
3722 genModOneByte (left, right, result);
3726 /* should have been converted to function call */
3730 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (result, NULL, ic, TRUE);
3735 /*-----------------------------------------------------------------*/
3736 /* genIfxJump :- will create a jump depending on the ifx */
3737 /*-----------------------------------------------------------------*/
3739 genIfxJump (iCode * ic, char *jval)
3742 symbol *tlbl = newiTempLabel (NULL);
3745 /* if true label then we jump if condition
3749 jlbl = IC_TRUE (ic);
3750 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3751 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3755 /* false label is present */
3756 jlbl = IC_FALSE (ic);
3757 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3758 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3760 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3761 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3763 emitcode (inst, "%05d$", tlbl->key + 100);
3764 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3765 emitcode ("", "%05d$:", tlbl->key + 100);
3767 /* mark the icode as generated */
3771 /*-----------------------------------------------------------------*/
3772 /* genCmp :- greater or less than comparison */
3773 /*-----------------------------------------------------------------*/
3775 genCmp (operand * left, operand * right,
3776 operand * result, iCode * ifx, int sign, iCode *ic)
3778 int size, offset = 0;
3779 unsigned long lit = 0L;
3781 /* if left & right are bit variables */
3782 if (AOP_TYPE (left) == AOP_CRY &&
3783 AOP_TYPE (right) == AOP_CRY)
3785 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3786 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3790 /* subtract right from left if at the
3791 end the carry flag is set then we know that
3792 left is greater than right */
3793 size = max (AOP_SIZE (left), AOP_SIZE (right));
3795 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3796 if ((size == 1) && !sign &&
3797 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3799 symbol *lbl = newiTempLabel (NULL);
3800 emitcode ("cjne", "%s,%s,%05d$",
3801 aopGet (AOP (left), offset, FALSE, FALSE),
3802 aopGet (AOP (right), offset, FALSE, FALSE),
3804 emitcode ("", "%05d$:", lbl->key + 100);
3808 if (AOP_TYPE (right) == AOP_LIT)
3810 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3811 /* optimize if(x < 0) or if(x >= 0) */
3820 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3821 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3823 genIfxJump (ifx, "acc.7");
3827 emitcode ("rlc", "a");
3835 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3836 if (sign && size == 0)
3838 emitcode ("xrl", "a,#0x80");
3839 if (AOP_TYPE (right) == AOP_LIT)
3841 unsigned long lit = (unsigned long)
3842 floatFromVal (AOP (right)->aopu.aop_lit);
3843 emitcode ("subb", "a,#0x%02x",
3844 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3848 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3849 emitcode ("xrl", "b,#0x80");
3850 emitcode ("subb", "a,b");
3854 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3860 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3861 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3862 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3868 /* if the result is used in the next
3869 ifx conditional branch then generate
3870 code a little differently */
3872 genIfxJump (ifx, "c");
3875 /* leave the result in acc */
3879 /*-----------------------------------------------------------------*/
3880 /* genCmpGt :- greater than comparison */
3881 /*-----------------------------------------------------------------*/
3883 genCmpGt (iCode * ic, iCode * ifx)
3885 operand *left, *right, *result;
3886 sym_link *letype, *retype;
3889 left = IC_LEFT (ic);
3890 right = IC_RIGHT (ic);
3891 result = IC_RESULT (ic);
3893 letype = getSpec (operandType (left));
3894 retype = getSpec (operandType (right));
3895 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3896 /* assign the amsops */
3897 aopOp (left, ic, FALSE);
3898 aopOp (right, ic, FALSE);
3899 aopOp (result, ic, TRUE);
3901 genCmp (right, left, result, ifx, sign,ic);
3903 freeAsmop (result, NULL, ic, TRUE);
3906 /*-----------------------------------------------------------------*/
3907 /* genCmpLt - less than comparisons */
3908 /*-----------------------------------------------------------------*/
3910 genCmpLt (iCode * ic, iCode * ifx)
3912 operand *left, *right, *result;
3913 sym_link *letype, *retype;
3916 left = IC_LEFT (ic);
3917 right = IC_RIGHT (ic);
3918 result = IC_RESULT (ic);
3920 letype = getSpec (operandType (left));
3921 retype = getSpec (operandType (right));
3922 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3924 /* assign the amsops */
3925 aopOp (left, ic, FALSE);
3926 aopOp (right, ic, FALSE);
3927 aopOp (result, ic, TRUE);
3929 genCmp (left, right, result, ifx, sign,ic);
3931 freeAsmop (result, NULL, ic, TRUE);
3934 /*-----------------------------------------------------------------*/
3935 /* gencjneshort - compare and jump if not equal */
3936 /*-----------------------------------------------------------------*/
3938 gencjneshort (operand * left, operand * right, symbol * lbl)
3940 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3942 unsigned long lit = 0L;
3944 /* if the left side is a literal or
3945 if the right is in a pointer register and left
3947 if ((AOP_TYPE (left) == AOP_LIT) ||
3948 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3954 if (AOP_TYPE (right) == AOP_LIT)
3955 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3957 /* if the right side is a literal then anything goes */
3958 if (AOP_TYPE (right) == AOP_LIT &&
3959 AOP_TYPE (left) != AOP_DIR)
3963 emitcode ("cjne", "%s,%s,%05d$",
3964 aopGet (AOP (left), offset, FALSE, FALSE),
3965 aopGet (AOP (right), offset, FALSE, FALSE),
3971 /* if the right side is in a register or in direct space or
3972 if the left is a pointer register & right is not */
3973 else if (AOP_TYPE (right) == AOP_REG ||
3974 AOP_TYPE (right) == AOP_DIR ||
3975 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3976 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3980 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3981 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3982 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3983 emitcode ("jnz", "%05d$", lbl->key + 100);
3985 emitcode ("cjne", "a,%s,%05d$",
3986 aopGet (AOP (right), offset, FALSE, TRUE),
3993 /* right is a pointer reg need both a & b */
3996 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3997 if (strcmp (l, "b"))
3998 emitcode ("mov", "b,%s", l);
3999 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4000 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4006 /*-----------------------------------------------------------------*/
4007 /* gencjne - compare and jump if not equal */
4008 /*-----------------------------------------------------------------*/
4010 gencjne (operand * left, operand * right, symbol * lbl)
4012 symbol *tlbl = newiTempLabel (NULL);
4014 gencjneshort (left, right, lbl);
4016 emitcode ("mov", "a,%s", one);
4017 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4018 emitcode ("", "%05d$:", lbl->key + 100);
4019 emitcode ("clr", "a");
4020 emitcode ("", "%05d$:", tlbl->key + 100);
4023 /*-----------------------------------------------------------------*/
4024 /* genCmpEq - generates code for equal to */
4025 /*-----------------------------------------------------------------*/
4027 genCmpEq (iCode * ic, iCode * ifx)
4029 operand *left, *right, *result;
4031 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4032 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4033 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4035 /* if literal, literal on the right or
4036 if the right is in a pointer register and left
4038 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4039 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4041 operand *t = IC_RIGHT (ic);
4042 IC_RIGHT (ic) = IC_LEFT (ic);
4046 if (ifx && !AOP_SIZE (result))
4049 /* if they are both bit variables */
4050 if (AOP_TYPE (left) == AOP_CRY &&
4051 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4053 if (AOP_TYPE (right) == AOP_LIT)
4055 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4059 emitcode ("cpl", "c");
4063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4067 emitcode ("clr", "c");
4069 /* AOP_TYPE(right) == AOP_CRY */
4073 symbol *lbl = newiTempLabel (NULL);
4074 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4075 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4076 emitcode ("cpl", "c");
4077 emitcode ("", "%05d$:", (lbl->key + 100));
4079 /* if true label then we jump if condition
4081 tlbl = newiTempLabel (NULL);
4084 emitcode ("jnc", "%05d$", tlbl->key + 100);
4085 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4089 emitcode ("jc", "%05d$", tlbl->key + 100);
4090 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4092 emitcode ("", "%05d$:", tlbl->key + 100);
4096 tlbl = newiTempLabel (NULL);
4097 gencjneshort (left, right, tlbl);
4100 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4101 emitcode ("", "%05d$:", tlbl->key + 100);
4105 symbol *lbl = newiTempLabel (NULL);
4106 emitcode ("sjmp", "%05d$", lbl->key + 100);
4107 emitcode ("", "%05d$:", tlbl->key + 100);
4108 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4109 emitcode ("", "%05d$:", lbl->key + 100);
4112 /* mark the icode as generated */
4117 /* if they are both bit variables */
4118 if (AOP_TYPE (left) == AOP_CRY &&
4119 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4121 if (AOP_TYPE (right) == AOP_LIT)
4123 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4126 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4127 emitcode ("cpl", "c");
4131 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4135 emitcode ("clr", "c");
4137 /* AOP_TYPE(right) == AOP_CRY */
4141 symbol *lbl = newiTempLabel (NULL);
4142 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4143 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4144 emitcode ("cpl", "c");
4145 emitcode ("", "%05d$:", (lbl->key + 100));
4148 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4155 genIfxJump (ifx, "c");
4158 /* if the result is used in an arithmetic operation
4159 then put the result in place */
4164 gencjne (left, right, newiTempLabel (NULL));
4165 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4167 aopPut (AOP (result), "a", 0);
4172 genIfxJump (ifx, "a");
4175 /* if the result is used in an arithmetic operation
4176 then put the result in place */
4177 if (AOP_TYPE (result) != AOP_CRY)
4179 /* leave the result in acc */
4183 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4184 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4185 freeAsmop (result, NULL, ic, TRUE);
4188 /*-----------------------------------------------------------------*/
4189 /* ifxForOp - returns the icode containing the ifx for operand */
4190 /*-----------------------------------------------------------------*/
4192 ifxForOp (operand * op, iCode * ic)
4194 /* if true symbol then needs to be assigned */
4195 if (IS_TRUE_SYMOP (op))
4198 /* if this has register type condition and
4199 the next instruction is ifx with the same operand
4200 and live to of the operand is upto the ifx only then */
4202 ic->next->op == IFX &&
4203 IC_COND (ic->next)->key == op->key &&
4204 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4210 /*-----------------------------------------------------------------*/
4211 /* hasInc - operand is incremented before any other use */
4212 /*-----------------------------------------------------------------*/
4214 hasInc (operand *op, iCode *ic)
4216 sym_link *type = operandType(op);
4217 sym_link *retype = getSpec (type);
4218 iCode *lic = ic->next;
4221 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4222 isize = getSize(type->next);
4224 /* if operand of the form op = op + <sizeof *op> */
4225 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4226 isOperandEqual(IC_RESULT(lic),op) &&
4227 isOperandLiteral(IC_RIGHT(lic)) &&
4228 operandLitValue(IC_RIGHT(lic)) == isize) {
4231 /* if the operand used or deffed */
4232 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4240 /*-----------------------------------------------------------------*/
4241 /* genAndOp - for && operation */
4242 /*-----------------------------------------------------------------*/
4244 genAndOp (iCode * ic)
4246 operand *left, *right, *result;
4249 /* note here that && operations that are in an
4250 if statement are taken away by backPatchLabels
4251 only those used in arthmetic operations remain */
4252 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4253 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4254 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4256 /* if both are bit variables */
4257 if (AOP_TYPE (left) == AOP_CRY &&
4258 AOP_TYPE (right) == AOP_CRY)
4260 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4261 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4266 tlbl = newiTempLabel (NULL);
4268 emitcode ("jz", "%05d$", tlbl->key + 100);
4270 emitcode ("", "%05d$:", tlbl->key + 100);
4274 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4275 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4276 freeAsmop (result, NULL, ic, TRUE);
4280 /*-----------------------------------------------------------------*/
4281 /* genOrOp - for || operation */
4282 /*-----------------------------------------------------------------*/
4284 genOrOp (iCode * ic)
4286 operand *left, *right, *result;
4289 /* note here that || operations that are in an
4290 if statement are taken away by backPatchLabels
4291 only those used in arthmetic operations remain */
4292 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4293 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4294 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4296 /* if both are bit variables */
4297 if (AOP_TYPE (left) == AOP_CRY &&
4298 AOP_TYPE (right) == AOP_CRY)
4300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4301 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4306 tlbl = newiTempLabel (NULL);
4308 emitcode ("jnz", "%05d$", tlbl->key + 100);
4310 emitcode ("", "%05d$:", tlbl->key + 100);
4314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4316 freeAsmop (result, NULL, ic, TRUE);
4319 /*-----------------------------------------------------------------*/
4320 /* isLiteralBit - test if lit == 2^n */
4321 /*-----------------------------------------------------------------*/
4323 isLiteralBit (unsigned long lit)
4325 unsigned long pw[32] =
4326 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4327 0x100L, 0x200L, 0x400L, 0x800L,
4328 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4329 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4330 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4331 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4332 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4335 for (idx = 0; idx < 32; idx++)
4341 /*-----------------------------------------------------------------*/
4342 /* continueIfTrue - */
4343 /*-----------------------------------------------------------------*/
4345 continueIfTrue (iCode * ic)
4348 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4352 /*-----------------------------------------------------------------*/
4354 /*-----------------------------------------------------------------*/
4356 jumpIfTrue (iCode * ic)
4359 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4363 /*-----------------------------------------------------------------*/
4364 /* jmpTrueOrFalse - */
4365 /*-----------------------------------------------------------------*/
4367 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4369 // ugly but optimized by peephole
4372 symbol *nlbl = newiTempLabel (NULL);
4373 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4374 emitcode ("", "%05d$:", tlbl->key + 100);
4375 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4376 emitcode ("", "%05d$:", nlbl->key + 100);
4380 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4381 emitcode ("", "%05d$:", tlbl->key + 100);
4386 /*-----------------------------------------------------------------*/
4387 /* genAnd - code for and */
4388 /*-----------------------------------------------------------------*/
4390 genAnd (iCode * ic, iCode * ifx)
4392 operand *left, *right, *result;
4393 int size, offset = 0;
4394 unsigned long lit = 0L;
4398 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4399 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4400 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4403 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4405 AOP_TYPE (left), AOP_TYPE (right));
4406 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4408 AOP_SIZE (left), AOP_SIZE (right));
4411 /* if left is a literal & right is not then exchange them */
4412 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4413 AOP_NEEDSACC (left))
4415 operand *tmp = right;
4420 /* if result = right then exchange them */
4421 if (sameRegs (AOP (result), AOP (right)))
4423 operand *tmp = right;
4428 /* if right is bit then exchange them */
4429 if (AOP_TYPE (right) == AOP_CRY &&
4430 AOP_TYPE (left) != AOP_CRY)
4432 operand *tmp = right;
4436 if (AOP_TYPE (right) == AOP_LIT)
4437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4439 size = AOP_SIZE (result);
4442 // result = bit & yy;
4443 if (AOP_TYPE (left) == AOP_CRY)
4445 // c = bit & literal;
4446 if (AOP_TYPE (right) == AOP_LIT)
4450 if (size && sameRegs (AOP (result), AOP (left)))
4453 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4458 if (size && (AOP_TYPE (result) == AOP_CRY))
4460 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4463 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4468 emitcode ("clr", "c");
4473 if (AOP_TYPE (right) == AOP_CRY)
4476 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4477 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4482 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4484 emitcode ("rrc", "a");
4485 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4493 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4494 genIfxJump (ifx, "c");
4498 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4499 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4500 if ((AOP_TYPE (right) == AOP_LIT) &&
4501 (AOP_TYPE (result) == AOP_CRY) &&
4502 (AOP_TYPE (left) != AOP_CRY))
4504 int posbit = isLiteralBit (lit);
4509 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4512 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4518 sprintf (buffer, "acc.%d", posbit & 0x07);
4519 genIfxJump (ifx, buffer);
4526 symbol *tlbl = newiTempLabel (NULL);
4527 int sizel = AOP_SIZE (left);
4529 emitcode ("setb", "c");
4532 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4534 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4536 if ((posbit = isLiteralBit (bytelit)) != 0)
4537 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4540 if (bytelit != 0x0FFL)
4541 emitcode ("anl", "a,%s",
4542 aopGet (AOP (right), offset, FALSE, TRUE));
4543 emitcode ("jnz", "%05d$", tlbl->key + 100);
4548 // bit = left & literal
4551 emitcode ("clr", "c");
4552 emitcode ("", "%05d$:", tlbl->key + 100);
4554 // if(left & literal)
4558 jmpTrueOrFalse (ifx, tlbl);
4566 /* if left is same as result */
4567 if (sameRegs (AOP (result), AOP (left)))
4569 for (; size--; offset++)
4571 if (AOP_TYPE (right) == AOP_LIT)
4573 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4575 else if (bytelit == 0)
4576 aopPut (AOP (result), zero, offset);
4577 else if (IS_AOP_PREG (result))
4579 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4580 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4581 aopPut (AOP (result), "a", offset);
4584 emitcode ("anl", "%s,%s",
4585 aopGet (AOP (left), offset, FALSE, TRUE),
4586 aopGet (AOP (right), offset, FALSE, FALSE));
4590 if (AOP_TYPE (left) == AOP_ACC)
4591 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4594 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4595 if (IS_AOP_PREG (result))
4597 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4598 aopPut (AOP (result), "a", offset);
4602 emitcode ("anl", "%s,a",
4603 aopGet (AOP (left), offset, FALSE, TRUE));
4610 // left & result in different registers
4611 if (AOP_TYPE (result) == AOP_CRY)
4614 // if(size), result in bit
4615 // if(!size && ifx), conditional oper: if(left & right)
4616 symbol *tlbl = newiTempLabel (NULL);
4617 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4619 emitcode ("setb", "c");
4622 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4623 emitcode ("anl", "a,%s",
4624 aopGet (AOP (right), offset, FALSE, FALSE));
4626 if (AOP_TYPE(left)==AOP_ACC) {
4627 emitcode("mov", "b,a");
4628 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4629 emitcode("anl", "a,b");
4631 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4632 emitcode ("anl", "a,%s",
4633 aopGet (AOP (left), offset, FALSE, FALSE));
4636 emitcode ("jnz", "%05d$", tlbl->key + 100);
4642 emitcode ("", "%05d$:", tlbl->key + 100);
4646 jmpTrueOrFalse (ifx, tlbl);
4650 for (; (size--); offset++)
4653 // result = left & right
4654 if (AOP_TYPE (right) == AOP_LIT)
4656 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4658 aopPut (AOP (result),
4659 aopGet (AOP (left), offset, FALSE, FALSE),
4663 else if (bytelit == 0)
4665 aopPut (AOP (result), zero, offset);
4669 // faster than result <- left, anl result,right
4670 // and better if result is SFR
4671 if (AOP_TYPE (left) == AOP_ACC)
4672 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4675 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4676 emitcode ("anl", "a,%s",
4677 aopGet (AOP (left), offset, FALSE, FALSE));
4679 aopPut (AOP (result), "a", offset);
4685 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (result, NULL, ic, TRUE);
4690 /*-----------------------------------------------------------------*/
4691 /* genOr - code for or */
4692 /*-----------------------------------------------------------------*/
4694 genOr (iCode * ic, iCode * ifx)
4696 operand *left, *right, *result;
4697 int size, offset = 0;
4698 unsigned long lit = 0L;
4700 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4701 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4702 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4705 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4707 AOP_TYPE (left), AOP_TYPE (right));
4708 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4710 AOP_SIZE (left), AOP_SIZE (right));
4713 /* if left is a literal & right is not then exchange them */
4714 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4715 AOP_NEEDSACC (left))
4717 operand *tmp = right;
4722 /* if result = right then exchange them */
4723 if (sameRegs (AOP (result), AOP (right)))
4725 operand *tmp = right;
4730 /* if right is bit then exchange them */
4731 if (AOP_TYPE (right) == AOP_CRY &&
4732 AOP_TYPE (left) != AOP_CRY)
4734 operand *tmp = right;
4738 if (AOP_TYPE (right) == AOP_LIT)
4739 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4741 size = AOP_SIZE (result);
4745 if (AOP_TYPE (left) == AOP_CRY)
4747 if (AOP_TYPE (right) == AOP_LIT)
4749 // c = bit & literal;
4752 // lit != 0 => result = 1
4753 if (AOP_TYPE (result) == AOP_CRY)
4756 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4758 continueIfTrue (ifx);
4761 emitcode ("setb", "c");
4765 // lit == 0 => result = left
4766 if (size && sameRegs (AOP (result), AOP (left)))
4768 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4773 if (AOP_TYPE (right) == AOP_CRY)
4776 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4777 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4782 symbol *tlbl = newiTempLabel (NULL);
4783 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4784 emitcode ("setb", "c");
4785 emitcode ("jb", "%s,%05d$",
4786 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4788 emitcode ("jnz", "%05d$", tlbl->key + 100);
4789 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4791 jmpTrueOrFalse (ifx, tlbl);
4797 emitcode ("", "%05d$:", tlbl->key + 100);
4806 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4807 genIfxJump (ifx, "c");
4811 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4812 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4813 if ((AOP_TYPE (right) == AOP_LIT) &&
4814 (AOP_TYPE (result) == AOP_CRY) &&
4815 (AOP_TYPE (left) != AOP_CRY))
4821 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4823 continueIfTrue (ifx);
4828 // lit = 0, result = boolean(left)
4830 emitcode ("setb", "c");
4834 symbol *tlbl = newiTempLabel (NULL);
4835 emitcode ("jnz", "%05d$", tlbl->key + 100);
4837 emitcode ("", "%05d$:", tlbl->key + 100);
4841 genIfxJump (ifx, "a");
4849 /* if left is same as result */
4850 if (sameRegs (AOP (result), AOP (left)))
4852 for (; size--; offset++)
4854 if (AOP_TYPE (right) == AOP_LIT)
4856 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4858 else if (IS_AOP_PREG (left))
4860 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4861 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4862 aopPut (AOP (result), "a", offset);
4865 emitcode ("orl", "%s,%s",
4866 aopGet (AOP (left), offset, FALSE, TRUE),
4867 aopGet (AOP (right), offset, FALSE, FALSE));
4871 if (AOP_TYPE (left) == AOP_ACC)
4872 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4875 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4876 if (IS_AOP_PREG (left))
4878 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4879 aopPut (AOP (result), "a", offset);
4882 emitcode ("orl", "%s,a",
4883 aopGet (AOP (left), offset, FALSE, TRUE));
4890 // left & result in different registers
4891 if (AOP_TYPE (result) == AOP_CRY)
4894 // if(size), result in bit
4895 // if(!size && ifx), conditional oper: if(left | right)
4896 symbol *tlbl = newiTempLabel (NULL);
4897 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4899 emitcode ("setb", "c");
4902 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4903 emitcode ("orl", "a,%s",
4904 aopGet (AOP (right), offset, FALSE, FALSE));
4906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4907 emitcode ("orl", "a,%s",
4908 aopGet (AOP (left), offset, FALSE, FALSE));
4910 emitcode ("jnz", "%05d$", tlbl->key + 100);
4916 emitcode ("", "%05d$:", tlbl->key + 100);
4920 jmpTrueOrFalse (ifx, tlbl);
4923 for (; (size--); offset++)
4926 // result = left & right
4927 if (AOP_TYPE (right) == AOP_LIT)
4929 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4931 aopPut (AOP (result),
4932 aopGet (AOP (left), offset, FALSE, FALSE),
4937 // faster than result <- left, anl result,right
4938 // and better if result is SFR
4939 if (AOP_TYPE (left) == AOP_ACC)
4940 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4943 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4944 emitcode ("orl", "a,%s",
4945 aopGet (AOP (left), offset, FALSE, FALSE));
4947 aopPut (AOP (result), "a", offset);
4952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4954 freeAsmop (result, NULL, ic, TRUE);
4957 /*-----------------------------------------------------------------*/
4958 /* genXor - code for xclusive or */
4959 /*-----------------------------------------------------------------*/
4961 genXor (iCode * ic, iCode * ifx)
4963 operand *left, *right, *result;
4964 int size, offset = 0;
4965 unsigned long lit = 0L;
4967 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4968 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4969 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4972 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4974 AOP_TYPE (left), AOP_TYPE (right));
4975 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4977 AOP_SIZE (left), AOP_SIZE (right));
4980 /* if left is a literal & right is not ||
4981 if left needs acc & right does not */
4982 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4983 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4985 operand *tmp = right;
4990 /* if result = right then exchange them */
4991 if (sameRegs (AOP (result), AOP (right)))
4993 operand *tmp = right;
4998 /* if right is bit then exchange them */
4999 if (AOP_TYPE (right) == AOP_CRY &&
5000 AOP_TYPE (left) != AOP_CRY)
5002 operand *tmp = right;
5006 if (AOP_TYPE (right) == AOP_LIT)
5007 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5009 size = AOP_SIZE (result);
5013 if (AOP_TYPE (left) == AOP_CRY)
5015 if (AOP_TYPE (right) == AOP_LIT)
5017 // c = bit & literal;
5020 // lit>>1 != 0 => result = 1
5021 if (AOP_TYPE (result) == AOP_CRY)
5024 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5026 continueIfTrue (ifx);
5029 emitcode ("setb", "c");
5036 // lit == 0, result = left
5037 if (size && sameRegs (AOP (result), AOP (left)))
5039 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5043 // lit == 1, result = not(left)
5044 if (size && sameRegs (AOP (result), AOP (left)))
5046 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5052 emitcode ("cpl", "c");
5061 symbol *tlbl = newiTempLabel (NULL);
5062 if (AOP_TYPE (right) == AOP_CRY)
5065 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5069 int sizer = AOP_SIZE (right);
5071 // if val>>1 != 0, result = 1
5072 emitcode ("setb", "c");
5075 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5077 // test the msb of the lsb
5078 emitcode ("anl", "a,#0xfe");
5079 emitcode ("jnz", "%05d$", tlbl->key + 100);
5083 emitcode ("rrc", "a");
5085 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5086 emitcode ("cpl", "c");
5087 emitcode ("", "%05d$:", (tlbl->key + 100));
5094 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5095 genIfxJump (ifx, "c");
5099 if (sameRegs (AOP (result), AOP (left)))
5101 /* if left is same as result */
5102 for (; size--; offset++)
5104 if (AOP_TYPE (right) == AOP_LIT)
5106 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5108 else if (IS_AOP_PREG (left))
5110 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5111 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5112 aopPut (AOP (result), "a", offset);
5115 emitcode ("xrl", "%s,%s",
5116 aopGet (AOP (left), offset, FALSE, TRUE),
5117 aopGet (AOP (right), offset, FALSE, FALSE));
5121 if (AOP_TYPE (left) == AOP_ACC)
5122 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5125 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5126 if (IS_AOP_PREG (left))
5128 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5129 aopPut (AOP (result), "a", offset);
5132 emitcode ("xrl", "%s,a",
5133 aopGet (AOP (left), offset, FALSE, TRUE));
5140 // left & result in different registers
5141 if (AOP_TYPE (result) == AOP_CRY)
5144 // if(size), result in bit
5145 // if(!size && ifx), conditional oper: if(left ^ right)
5146 symbol *tlbl = newiTempLabel (NULL);
5147 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5149 emitcode ("setb", "c");
5152 if ((AOP_TYPE (right) == AOP_LIT) &&
5153 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5155 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5159 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5160 emitcode ("xrl", "a,%s",
5161 aopGet (AOP (right), offset, FALSE, FALSE));
5163 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5164 emitcode ("xrl", "a,%s",
5165 aopGet (AOP (left), offset, FALSE, FALSE));
5168 emitcode ("jnz", "%05d$", tlbl->key + 100);
5174 emitcode ("", "%05d$:", tlbl->key + 100);
5178 jmpTrueOrFalse (ifx, tlbl);
5181 for (; (size--); offset++)
5184 // result = left & right
5185 if (AOP_TYPE (right) == AOP_LIT)
5187 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5189 aopPut (AOP (result),
5190 aopGet (AOP (left), offset, FALSE, FALSE),
5195 // faster than result <- left, anl result,right
5196 // and better if result is SFR
5197 if (AOP_TYPE (left) == AOP_ACC)
5198 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5202 emitcode ("xrl", "a,%s",
5203 aopGet (AOP (left), offset, FALSE, TRUE));
5205 aopPut (AOP (result), "a", offset);
5210 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5211 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5212 freeAsmop (result, NULL, ic, TRUE);
5215 /*-----------------------------------------------------------------*/
5216 /* genInline - write the inline code out */
5217 /*-----------------------------------------------------------------*/
5219 genInline (iCode * ic)
5221 char *buffer, *bp, *bp1;
5223 _G.inLine += (!options.asmpeep);
5225 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5226 strcpy (buffer, IC_INLINE (ic));
5228 /* emit each line as a code */
5253 /* emitcode("",buffer); */
5254 _G.inLine -= (!options.asmpeep);
5257 /*-----------------------------------------------------------------*/
5258 /* genRRC - rotate right with carry */
5259 /*-----------------------------------------------------------------*/
5263 operand *left, *result;
5264 int size, offset = 0;
5267 /* rotate right with carry */
5268 left = IC_LEFT (ic);
5269 result = IC_RESULT (ic);
5270 aopOp (left, ic, FALSE);
5271 aopOp (result, ic, FALSE);
5273 /* move it to the result */
5274 size = AOP_SIZE (result);
5276 if (size == 1) { /* special case for 1 byte */
5277 l = aopGet (AOP (left), offset, FALSE, FALSE);
5279 emitcode ("rr", "a");
5285 l = aopGet (AOP (left), offset, FALSE, FALSE);
5287 emitcode ("rrc", "a");
5288 if (AOP_SIZE (result) > 1)
5289 aopPut (AOP (result), "a", offset--);
5291 /* now we need to put the carry into the
5292 highest order byte of the result */
5293 if (AOP_SIZE (result) > 1)
5295 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5298 emitcode ("mov", "acc.7,c");
5300 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5301 freeAsmop (left, NULL, ic, TRUE);
5302 freeAsmop (result, NULL, ic, TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* genRLC - generate code for rotate left with carry */
5307 /*-----------------------------------------------------------------*/
5311 operand *left, *result;
5312 int size, offset = 0;
5315 /* rotate right with carry */
5316 left = IC_LEFT (ic);
5317 result = IC_RESULT (ic);
5318 aopOp (left, ic, FALSE);
5319 aopOp (result, ic, FALSE);
5321 /* move it to the result */
5322 size = AOP_SIZE (result);
5326 l = aopGet (AOP (left), offset, FALSE, FALSE);
5328 if (size == 0) { /* special case for 1 byte */
5332 emitcode ("add", "a,acc");
5333 if (AOP_SIZE (result) > 1)
5334 aopPut (AOP (result), "a", offset++);
5337 l = aopGet (AOP (left), offset, FALSE, FALSE);
5339 emitcode ("rlc", "a");
5340 if (AOP_SIZE (result) > 1)
5341 aopPut (AOP (result), "a", offset++);
5344 /* now we need to put the carry into the
5345 highest order byte of the result */
5346 if (AOP_SIZE (result) > 1)
5348 l = aopGet (AOP (result), 0, FALSE, FALSE);
5351 emitcode ("mov", "acc.0,c");
5353 aopPut (AOP (result), "a", 0);
5354 freeAsmop (left, NULL, ic, TRUE);
5355 freeAsmop (result, NULL, ic, TRUE);
5358 /*-----------------------------------------------------------------*/
5359 /* genGetHbit - generates code get highest order bit */
5360 /*-----------------------------------------------------------------*/
5362 genGetHbit (iCode * ic)
5364 operand *left, *result;
5365 left = IC_LEFT (ic);
5366 result = IC_RESULT (ic);
5367 aopOp (left, ic, FALSE);
5368 aopOp (result, ic, FALSE);
5370 /* get the highest order byte into a */
5371 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5372 if (AOP_TYPE (result) == AOP_CRY)
5374 emitcode ("rlc", "a");
5379 emitcode ("rl", "a");
5380 emitcode ("anl", "a,#0x01");
5385 freeAsmop (left, NULL, ic, TRUE);
5386 freeAsmop (result, NULL, ic, TRUE);
5389 /*-----------------------------------------------------------------*/
5390 /* AccRol - rotate left accumulator by known count */
5391 /*-----------------------------------------------------------------*/
5393 AccRol (int shCount)
5395 shCount &= 0x0007; // shCount : 0..7
5402 emitcode ("rl", "a");
5405 emitcode ("rl", "a");
5406 emitcode ("rl", "a");
5409 emitcode ("swap", "a");
5410 emitcode ("rr", "a");
5413 emitcode ("swap", "a");
5416 emitcode ("swap", "a");
5417 emitcode ("rl", "a");
5420 emitcode ("rr", "a");
5421 emitcode ("rr", "a");
5424 emitcode ("rr", "a");
5429 /*-----------------------------------------------------------------*/
5430 /* AccLsh - left shift accumulator by known count */
5431 /*-----------------------------------------------------------------*/
5433 AccLsh (int shCount)
5438 emitcode ("add", "a,acc");
5439 else if (shCount == 2)
5441 emitcode ("add", "a,acc");
5442 emitcode ("add", "a,acc");
5446 /* rotate left accumulator */
5448 /* and kill the lower order bits */
5449 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5454 /*-----------------------------------------------------------------*/
5455 /* AccRsh - right shift accumulator by known count */
5456 /*-----------------------------------------------------------------*/
5458 AccRsh (int shCount)
5465 emitcode ("rrc", "a");
5469 /* rotate right accumulator */
5470 AccRol (8 - shCount);
5471 /* and kill the higher order bits */
5472 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5477 /*-----------------------------------------------------------------*/
5478 /* AccSRsh - signed right shift accumulator by known count */
5479 /*-----------------------------------------------------------------*/
5481 AccSRsh (int shCount)
5488 emitcode ("mov", "c,acc.7");
5489 emitcode ("rrc", "a");
5491 else if (shCount == 2)
5493 emitcode ("mov", "c,acc.7");
5494 emitcode ("rrc", "a");
5495 emitcode ("mov", "c,acc.7");
5496 emitcode ("rrc", "a");
5500 tlbl = newiTempLabel (NULL);
5501 /* rotate right accumulator */
5502 AccRol (8 - shCount);
5503 /* and kill the higher order bits */
5504 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5505 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5506 emitcode ("orl", "a,#0x%02x",
5507 (unsigned char) ~SRMask[shCount]);
5508 emitcode ("", "%05d$:", tlbl->key + 100);
5513 /*-----------------------------------------------------------------*/
5514 /* shiftR1Left2Result - shift right one byte from left to result */
5515 /*-----------------------------------------------------------------*/
5517 shiftR1Left2Result (operand * left, int offl,
5518 operand * result, int offr,
5519 int shCount, int sign)
5521 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5522 /* shift right accumulator */
5527 aopPut (AOP (result), "a", offr);
5530 /*-----------------------------------------------------------------*/
5531 /* shiftL1Left2Result - shift left one byte from left to result */
5532 /*-----------------------------------------------------------------*/
5534 shiftL1Left2Result (operand * left, int offl,
5535 operand * result, int offr, int shCount)
5538 l = aopGet (AOP (left), offl, FALSE, FALSE);
5540 /* shift left accumulator */
5542 aopPut (AOP (result), "a", offr);
5545 /*-----------------------------------------------------------------*/
5546 /* movLeft2Result - move byte from left to result */
5547 /*-----------------------------------------------------------------*/
5549 movLeft2Result (operand * left, int offl,
5550 operand * result, int offr, int sign)
5553 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5555 l = aopGet (AOP (left), offl, FALSE, FALSE);
5557 if (*l == '@' && (IS_AOP_PREG (result)))
5559 emitcode ("mov", "a,%s", l);
5560 aopPut (AOP (result), "a", offr);
5565 aopPut (AOP (result), l, offr);
5568 /* MSB sign in acc.7 ! */
5569 if (getDataSize (left) == offl + 1)
5571 emitcode ("mov", "a,%s", l);
5572 aopPut (AOP (result), "a", offr);
5579 /*-----------------------------------------------------------------*/
5580 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5581 /*-----------------------------------------------------------------*/
5585 emitcode ("rrc", "a");
5586 emitcode ("xch", "a,%s", x);
5587 emitcode ("rrc", "a");
5588 emitcode ("xch", "a,%s", x);
5591 /*-----------------------------------------------------------------*/
5592 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5593 /*-----------------------------------------------------------------*/
5597 emitcode ("xch", "a,%s", x);
5598 emitcode ("rlc", "a");
5599 emitcode ("xch", "a,%s", x);
5600 emitcode ("rlc", "a");
5603 /*-----------------------------------------------------------------*/
5604 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5605 /*-----------------------------------------------------------------*/
5609 emitcode ("xch", "a,%s", x);
5610 emitcode ("add", "a,acc");
5611 emitcode ("xch", "a,%s", x);
5612 emitcode ("rlc", "a");
5615 /*-----------------------------------------------------------------*/
5616 /* AccAXLsh - left shift a:x by known count (0..7) */
5617 /*-----------------------------------------------------------------*/
5619 AccAXLsh (char *x, int shCount)
5634 case 5: // AAAAABBB:CCCCCDDD
5636 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5638 emitcode ("anl", "a,#0x%02x",
5639 SLMask[shCount]); // BBB00000:CCCCCDDD
5641 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5643 AccRol (shCount); // DDDCCCCC:BBB00000
5645 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5647 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5649 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5651 emitcode ("anl", "a,#0x%02x",
5652 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5654 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5656 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5659 case 6: // AAAAAABB:CCCCCCDD
5660 emitcode ("anl", "a,#0x%02x",
5661 SRMask[shCount]); // 000000BB:CCCCCCDD
5662 emitcode ("mov", "c,acc.0"); // c = B
5663 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5665 AccAXRrl1 (x); // BCCCCCCD:D000000B
5666 AccAXRrl1 (x); // BBCCCCCC:DD000000
5668 emitcode("rrc","a");
5669 emitcode("xch","a,%s", x);
5670 emitcode("rrc","a");
5671 emitcode("mov","c,acc.0"); //<< get correct bit
5672 emitcode("xch","a,%s", x);
5674 emitcode("rrc","a");
5675 emitcode("xch","a,%s", x);
5676 emitcode("rrc","a");
5677 emitcode("xch","a,%s", x);
5680 case 7: // a:x <<= 7
5682 emitcode ("anl", "a,#0x%02x",
5683 SRMask[shCount]); // 0000000B:CCCCCCCD
5685 emitcode ("mov", "c,acc.0"); // c = B
5687 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5689 AccAXRrl1 (x); // BCCCCCCC:D0000000
5697 /*-----------------------------------------------------------------*/
5698 /* AccAXRsh - right shift a:x known count (0..7) */
5699 /*-----------------------------------------------------------------*/
5701 AccAXRsh (char *x, int shCount)
5709 AccAXRrl1 (x); // 0->a:x
5714 AccAXRrl1 (x); // 0->a:x
5717 AccAXRrl1 (x); // 0->a:x
5722 case 5: // AAAAABBB:CCCCCDDD = a:x
5724 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5726 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5728 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5730 emitcode ("anl", "a,#0x%02x",
5731 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5733 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5735 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5737 emitcode ("anl", "a,#0x%02x",
5738 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5740 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5742 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5744 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5747 case 6: // AABBBBBB:CCDDDDDD
5749 emitcode ("mov", "c,acc.7");
5750 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5752 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5754 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5756 emitcode ("anl", "a,#0x%02x",
5757 SRMask[shCount]); // 000000AA:BBBBBBCC
5760 case 7: // ABBBBBBB:CDDDDDDD
5762 emitcode ("mov", "c,acc.7"); // c = A
5764 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5766 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5768 emitcode ("anl", "a,#0x%02x",
5769 SRMask[shCount]); // 0000000A:BBBBBBBC
5777 /*-----------------------------------------------------------------*/
5778 /* AccAXRshS - right shift signed a:x known count (0..7) */
5779 /*-----------------------------------------------------------------*/
5781 AccAXRshS (char *x, int shCount)
5789 emitcode ("mov", "c,acc.7");
5790 AccAXRrl1 (x); // s->a:x
5794 emitcode ("mov", "c,acc.7");
5795 AccAXRrl1 (x); // s->a:x
5797 emitcode ("mov", "c,acc.7");
5798 AccAXRrl1 (x); // s->a:x
5803 case 5: // AAAAABBB:CCCCCDDD = a:x
5805 tlbl = newiTempLabel (NULL);
5806 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5808 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5810 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5812 emitcode ("anl", "a,#0x%02x",
5813 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5815 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5817 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5819 emitcode ("anl", "a,#0x%02x",
5820 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5822 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5824 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5826 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5828 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5829 emitcode ("orl", "a,#0x%02x",
5830 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5832 emitcode ("", "%05d$:", tlbl->key + 100);
5833 break; // SSSSAAAA:BBBCCCCC
5835 case 6: // AABBBBBB:CCDDDDDD
5837 tlbl = newiTempLabel (NULL);
5838 emitcode ("mov", "c,acc.7");
5839 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5841 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5843 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5845 emitcode ("anl", "a,#0x%02x",
5846 SRMask[shCount]); // 000000AA:BBBBBBCC
5848 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5849 emitcode ("orl", "a,#0x%02x",
5850 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5852 emitcode ("", "%05d$:", tlbl->key + 100);
5854 case 7: // ABBBBBBB:CDDDDDDD
5856 tlbl = newiTempLabel (NULL);
5857 emitcode ("mov", "c,acc.7"); // c = A
5859 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5861 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5863 emitcode ("anl", "a,#0x%02x",
5864 SRMask[shCount]); // 0000000A:BBBBBBBC
5866 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5867 emitcode ("orl", "a,#0x%02x",
5868 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5870 emitcode ("", "%05d$:", tlbl->key + 100);
5877 /*-----------------------------------------------------------------*/
5878 /* shiftL2Left2Result - shift left two bytes from left to result */
5879 /*-----------------------------------------------------------------*/
5881 shiftL2Left2Result (operand * left, int offl,
5882 operand * result, int offr, int shCount)
5884 if (sameRegs (AOP (result), AOP (left)) &&
5885 ((offl + MSB16) == offr))
5887 /* don't crash result[offr] */
5888 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5889 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5893 movLeft2Result (left, offl, result, offr, 0);
5894 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5896 /* ax << shCount (x = lsb(result)) */
5897 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5898 aopPut (AOP (result), "a", offr + MSB16);
5902 /*-----------------------------------------------------------------*/
5903 /* shiftR2Left2Result - shift right two bytes from left to result */
5904 /*-----------------------------------------------------------------*/
5906 shiftR2Left2Result (operand * left, int offl,
5907 operand * result, int offr,
5908 int shCount, int sign)
5910 if (sameRegs (AOP (result), AOP (left)) &&
5911 ((offl + MSB16) == offr))
5913 /* don't crash result[offr] */
5914 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5915 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5919 movLeft2Result (left, offl, result, offr, 0);
5920 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5922 /* a:x >> shCount (x = lsb(result)) */
5924 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5926 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5927 if (getDataSize (result) > 1)
5928 aopPut (AOP (result), "a", offr + MSB16);
5931 /*-----------------------------------------------------------------*/
5932 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5933 /*-----------------------------------------------------------------*/
5935 shiftLLeftOrResult (operand * left, int offl,
5936 operand * result, int offr, int shCount)
5938 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5939 /* shift left accumulator */
5941 /* or with result */
5942 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5943 /* back to result */
5944 aopPut (AOP (result), "a", offr);
5947 /*-----------------------------------------------------------------*/
5948 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5949 /*-----------------------------------------------------------------*/
5951 shiftRLeftOrResult (operand * left, int offl,
5952 operand * result, int offr, int shCount)
5954 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5955 /* shift right accumulator */
5957 /* or with result */
5958 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5959 /* back to result */
5960 aopPut (AOP (result), "a", offr);
5963 /*-----------------------------------------------------------------*/
5964 /* genlshOne - left shift a one byte quantity by known count */
5965 /*-----------------------------------------------------------------*/
5967 genlshOne (operand * result, operand * left, int shCount)
5969 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5972 /*-----------------------------------------------------------------*/
5973 /* genlshTwo - left shift two bytes by known amount != 0 */
5974 /*-----------------------------------------------------------------*/
5976 genlshTwo (operand * result, operand * left, int shCount)
5980 size = getDataSize (result);
5982 /* if shCount >= 8 */
5990 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5992 movLeft2Result (left, LSB, result, MSB16, 0);
5994 aopPut (AOP (result), zero, LSB);
5997 /* 1 <= shCount <= 7 */
6001 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6003 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6007 /*-----------------------------------------------------------------*/
6008 /* shiftLLong - shift left one long from left to result */
6009 /* offl = LSB or MSB16 */
6010 /*-----------------------------------------------------------------*/
6012 shiftLLong (operand * left, operand * result, int offr)
6015 int size = AOP_SIZE (result);
6017 if (size >= LSB + offr)
6019 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6021 emitcode ("add", "a,acc");
6022 if (sameRegs (AOP (left), AOP (result)) &&
6023 size >= MSB16 + offr && offr != LSB)
6024 emitcode ("xch", "a,%s",
6025 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6027 aopPut (AOP (result), "a", LSB + offr);
6030 if (size >= MSB16 + offr)
6032 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6034 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6037 emitcode ("rlc", "a");
6038 if (sameRegs (AOP (left), AOP (result)) &&
6039 size >= MSB24 + offr && offr != LSB)
6040 emitcode ("xch", "a,%s",
6041 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6043 aopPut (AOP (result), "a", MSB16 + offr);
6046 if (size >= MSB24 + offr)
6048 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6050 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6053 emitcode ("rlc", "a");
6054 if (sameRegs (AOP (left), AOP (result)) &&
6055 size >= MSB32 + offr && offr != LSB)
6056 emitcode ("xch", "a,%s",
6057 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6059 aopPut (AOP (result), "a", MSB24 + offr);
6062 if (size > MSB32 + offr)
6064 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6066 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6069 emitcode ("rlc", "a");
6070 aopPut (AOP (result), "a", MSB32 + offr);
6073 aopPut (AOP (result), zero, LSB);
6076 /*-----------------------------------------------------------------*/
6077 /* genlshFour - shift four byte by a known amount != 0 */
6078 /*-----------------------------------------------------------------*/
6080 genlshFour (operand * result, operand * left, int shCount)
6084 size = AOP_SIZE (result);
6086 /* if shifting more that 3 bytes */
6091 /* lowest order of left goes to the highest
6092 order of the destination */
6093 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6095 movLeft2Result (left, LSB, result, MSB32, 0);
6096 aopPut (AOP (result), zero, LSB);
6097 aopPut (AOP (result), zero, MSB16);
6098 aopPut (AOP (result), zero, MSB24);
6102 /* more than two bytes */
6103 else if (shCount >= 16)
6105 /* lower order two bytes goes to higher order two bytes */
6107 /* if some more remaining */
6109 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6112 movLeft2Result (left, MSB16, result, MSB32, 0);
6113 movLeft2Result (left, LSB, result, MSB24, 0);
6115 aopPut (AOP (result), zero, MSB16);
6116 aopPut (AOP (result), zero, LSB);
6120 /* if more than 1 byte */
6121 else if (shCount >= 8)
6123 /* lower order three bytes goes to higher order three bytes */
6128 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6130 movLeft2Result (left, LSB, result, MSB16, 0);
6136 movLeft2Result (left, MSB24, result, MSB32, 0);
6137 movLeft2Result (left, MSB16, result, MSB24, 0);
6138 movLeft2Result (left, LSB, result, MSB16, 0);
6139 aopPut (AOP (result), zero, LSB);
6141 else if (shCount == 1)
6142 shiftLLong (left, result, MSB16);
6145 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6146 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6147 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6148 aopPut (AOP (result), zero, LSB);
6153 /* 1 <= shCount <= 7 */
6154 else if (shCount <= 2)
6156 shiftLLong (left, result, LSB);
6158 shiftLLong (result, result, LSB);
6160 /* 3 <= shCount <= 7, optimize */
6163 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6164 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6165 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6169 /*-----------------------------------------------------------------*/
6170 /* genLeftShiftLiteral - left shifting by known count */
6171 /*-----------------------------------------------------------------*/
6173 genLeftShiftLiteral (operand * left,
6178 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6181 freeAsmop (right, NULL, ic, TRUE);
6183 aopOp (left, ic, FALSE);
6184 aopOp (result, ic, FALSE);
6186 size = getSize (operandType (result));
6189 emitcode ("; shift left ", "result %d, left %d", size,
6193 /* I suppose that the left size >= result size */
6198 movLeft2Result (left, size, result, size, 0);
6202 else if (shCount >= (size * 8))
6204 aopPut (AOP (result), zero, size);
6210 genlshOne (result, left, shCount);
6214 genlshTwo (result, left, shCount);
6218 genlshFour (result, left, shCount);
6221 fprintf(stderr, "*** ack! mystery literal shift!\n");
6225 freeAsmop (left, NULL, ic, TRUE);
6226 freeAsmop (result, NULL, ic, TRUE);
6229 /*-----------------------------------------------------------------*/
6230 /* genLeftShift - generates code for left shifting */
6231 /*-----------------------------------------------------------------*/
6233 genLeftShift (iCode * ic)
6235 operand *left, *right, *result;
6238 symbol *tlbl, *tlbl1;
6240 right = IC_RIGHT (ic);
6241 left = IC_LEFT (ic);
6242 result = IC_RESULT (ic);
6244 aopOp (right, ic, FALSE);
6246 /* if the shift count is known then do it
6247 as efficiently as possible */
6248 if (AOP_TYPE (right) == AOP_LIT)
6250 genLeftShiftLiteral (left, right, result, ic);
6254 /* shift count is unknown then we have to form
6255 a loop get the loop count in B : Note: we take
6256 only the lower order byte since shifting
6257 more that 32 bits make no sense anyway, ( the
6258 largest size of an object can be only 32 bits ) */
6260 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6261 emitcode ("inc", "b");
6262 freeAsmop (right, NULL, ic, TRUE);
6263 aopOp (left, ic, FALSE);
6264 aopOp (result, ic, FALSE);
6266 /* now move the left to the result if they are not the
6268 if (!sameRegs (AOP (left), AOP (result)) &&
6269 AOP_SIZE (result) > 1)
6272 size = AOP_SIZE (result);
6276 l = aopGet (AOP (left), offset, FALSE, TRUE);
6277 if (*l == '@' && (IS_AOP_PREG (result)))
6280 emitcode ("mov", "a,%s", l);
6281 aopPut (AOP (result), "a", offset);
6284 aopPut (AOP (result), l, offset);
6289 tlbl = newiTempLabel (NULL);
6290 size = AOP_SIZE (result);
6292 tlbl1 = newiTempLabel (NULL);
6294 /* if it is only one byte then */
6297 symbol *tlbl1 = newiTempLabel (NULL);
6299 l = aopGet (AOP (left), 0, FALSE, FALSE);
6301 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6302 emitcode ("", "%05d$:", tlbl->key + 100);
6303 emitcode ("add", "a,acc");
6304 emitcode ("", "%05d$:", tlbl1->key + 100);
6305 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6306 aopPut (AOP (result), "a", 0);
6310 reAdjustPreg (AOP (result));
6312 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6313 emitcode ("", "%05d$:", tlbl->key + 100);
6314 l = aopGet (AOP (result), offset, FALSE, FALSE);
6316 emitcode ("add", "a,acc");
6317 aopPut (AOP (result), "a", offset++);
6320 l = aopGet (AOP (result), offset, FALSE, FALSE);
6322 emitcode ("rlc", "a");
6323 aopPut (AOP (result), "a", offset++);
6325 reAdjustPreg (AOP (result));
6327 emitcode ("", "%05d$:", tlbl1->key + 100);
6328 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6330 freeAsmop (left, NULL, ic, TRUE);
6331 freeAsmop (result, NULL, ic, TRUE);
6334 /*-----------------------------------------------------------------*/
6335 /* genrshOne - right shift a one byte quantity by known count */
6336 /*-----------------------------------------------------------------*/
6338 genrshOne (operand * result, operand * left,
6339 int shCount, int sign)
6341 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6344 /*-----------------------------------------------------------------*/
6345 /* genrshTwo - right shift two bytes by known amount != 0 */
6346 /*-----------------------------------------------------------------*/
6348 genrshTwo (operand * result, operand * left,
6349 int shCount, int sign)
6351 /* if shCount >= 8 */
6356 shiftR1Left2Result (left, MSB16, result, LSB,
6359 movLeft2Result (left, MSB16, result, LSB, sign);
6360 addSign (result, MSB16, sign);
6363 /* 1 <= shCount <= 7 */
6365 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6368 /*-----------------------------------------------------------------*/
6369 /* shiftRLong - shift right one long from left to result */
6370 /* offl = LSB or MSB16 */
6371 /*-----------------------------------------------------------------*/
6373 shiftRLong (operand * left, int offl,
6374 operand * result, int sign)
6376 int isSameRegs=sameRegs(AOP(left),AOP(result));
6378 if (isSameRegs && offl>1) {
6379 // we are in big trouble, but this shouldn't happen
6380 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6383 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6388 emitcode ("rlc", "a");
6389 emitcode ("subb", "a,acc");
6390 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6392 aopPut (AOP(result), zero, MSB32);
6397 emitcode ("clr", "c");
6399 emitcode ("mov", "c,acc.7");
6402 emitcode ("rrc", "a");
6404 if (isSameRegs && offl==MSB16) {
6405 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6407 aopPut (AOP (result), "a", MSB32);
6408 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6411 emitcode ("rrc", "a");
6412 if (isSameRegs && offl==1) {
6413 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6415 aopPut (AOP (result), "a", MSB24);
6416 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6418 emitcode ("rrc", "a");
6419 aopPut (AOP (result), "a", MSB16 - offl);
6423 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6424 emitcode ("rrc", "a");
6425 aopPut (AOP (result), "a", LSB);
6429 /*-----------------------------------------------------------------*/
6430 /* genrshFour - shift four byte by a known amount != 0 */
6431 /*-----------------------------------------------------------------*/
6433 genrshFour (operand * result, operand * left,
6434 int shCount, int sign)
6436 /* if shifting more that 3 bytes */
6441 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6443 movLeft2Result (left, MSB32, result, LSB, sign);
6444 addSign (result, MSB16, sign);
6446 else if (shCount >= 16)
6450 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6453 movLeft2Result (left, MSB24, result, LSB, 0);
6454 movLeft2Result (left, MSB32, result, MSB16, sign);
6456 addSign (result, MSB24, sign);
6458 else if (shCount >= 8)
6462 shiftRLong (left, MSB16, result, sign);
6463 else if (shCount == 0)
6465 movLeft2Result (left, MSB16, result, LSB, 0);
6466 movLeft2Result (left, MSB24, result, MSB16, 0);
6467 movLeft2Result (left, MSB32, result, MSB24, sign);
6468 addSign (result, MSB32, sign);
6472 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6473 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6474 /* the last shift is signed */
6475 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6476 addSign (result, MSB32, sign);
6480 { /* 1 <= shCount <= 7 */
6483 shiftRLong (left, LSB, result, sign);
6485 shiftRLong (result, LSB, result, sign);
6489 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6490 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6491 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6496 /*-----------------------------------------------------------------*/
6497 /* genRightShiftLiteral - right shifting by known count */
6498 /*-----------------------------------------------------------------*/
6500 genRightShiftLiteral (operand * left,
6506 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6509 freeAsmop (right, NULL, ic, TRUE);
6511 aopOp (left, ic, FALSE);
6512 aopOp (result, ic, FALSE);
6515 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6519 size = getDataSize (left);
6520 /* test the LEFT size !!! */
6522 /* I suppose that the left size >= result size */
6525 size = getDataSize (result);
6527 movLeft2Result (left, size, result, size, 0);
6530 else if (shCount >= (size * 8))
6533 /* get sign in acc.7 */
6534 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6535 addSign (result, LSB, sign);
6542 genrshOne (result, left, shCount, sign);
6546 genrshTwo (result, left, shCount, sign);
6550 genrshFour (result, left, shCount, sign);
6556 freeAsmop (left, NULL, ic, TRUE);
6557 freeAsmop (result, NULL, ic, TRUE);
6561 /*-----------------------------------------------------------------*/
6562 /* genSignedRightShift - right shift of signed number */
6563 /*-----------------------------------------------------------------*/
6565 genSignedRightShift (iCode * ic)
6567 operand *right, *left, *result;
6570 symbol *tlbl, *tlbl1;
6572 /* we do it the hard way put the shift count in b
6573 and loop thru preserving the sign */
6575 right = IC_RIGHT (ic);
6576 left = IC_LEFT (ic);
6577 result = IC_RESULT (ic);
6579 aopOp (right, ic, FALSE);
6582 if (AOP_TYPE (right) == AOP_LIT)
6584 genRightShiftLiteral (left, right, result, ic, 1);
6587 /* shift count is unknown then we have to form
6588 a loop get the loop count in B : Note: we take
6589 only the lower order byte since shifting
6590 more that 32 bits make no sense anyway, ( the
6591 largest size of an object can be only 32 bits ) */
6593 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6594 emitcode ("inc", "b");
6595 freeAsmop (right, NULL, ic, TRUE);
6596 aopOp (left, ic, FALSE);
6597 aopOp (result, ic, FALSE);
6599 /* now move the left to the result if they are not the
6601 if (!sameRegs (AOP (left), AOP (result)) &&
6602 AOP_SIZE (result) > 1)
6605 size = AOP_SIZE (result);
6609 l = aopGet (AOP (left), offset, FALSE, TRUE);
6610 if (*l == '@' && IS_AOP_PREG (result))
6613 emitcode ("mov", "a,%s", l);
6614 aopPut (AOP (result), "a", offset);
6617 aopPut (AOP (result), l, offset);
6622 /* mov the highest order bit to OVR */
6623 tlbl = newiTempLabel (NULL);
6624 tlbl1 = newiTempLabel (NULL);
6626 size = AOP_SIZE (result);
6628 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6629 emitcode ("rlc", "a");
6630 emitcode ("mov", "ov,c");
6631 /* if it is only one byte then */
6634 l = aopGet (AOP (left), 0, FALSE, FALSE);
6636 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6637 emitcode ("", "%05d$:", tlbl->key + 100);
6638 emitcode ("mov", "c,ov");
6639 emitcode ("rrc", "a");
6640 emitcode ("", "%05d$:", tlbl1->key + 100);
6641 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6642 aopPut (AOP (result), "a", 0);
6646 reAdjustPreg (AOP (result));
6647 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6648 emitcode ("", "%05d$:", tlbl->key + 100);
6649 emitcode ("mov", "c,ov");
6652 l = aopGet (AOP (result), offset, FALSE, FALSE);
6654 emitcode ("rrc", "a");
6655 aopPut (AOP (result), "a", offset--);
6657 reAdjustPreg (AOP (result));
6658 emitcode ("", "%05d$:", tlbl1->key + 100);
6659 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6662 freeAsmop (left, NULL, ic, TRUE);
6663 freeAsmop (result, NULL, ic, TRUE);
6666 /*-----------------------------------------------------------------*/
6667 /* genRightShift - generate code for right shifting */
6668 /*-----------------------------------------------------------------*/
6670 genRightShift (iCode * ic)
6672 operand *right, *left, *result;
6676 symbol *tlbl, *tlbl1;
6678 /* if signed then we do it the hard way preserve the
6679 sign bit moving it inwards */
6680 retype = getSpec (operandType (IC_RESULT (ic)));
6682 if (!SPEC_USIGN (retype))
6684 genSignedRightShift (ic);
6688 /* signed & unsigned types are treated the same : i.e. the
6689 signed is NOT propagated inwards : quoting from the
6690 ANSI - standard : "for E1 >> E2, is equivalent to division
6691 by 2**E2 if unsigned or if it has a non-negative value,
6692 otherwise the result is implementation defined ", MY definition
6693 is that the sign does not get propagated */
6695 right = IC_RIGHT (ic);
6696 left = IC_LEFT (ic);
6697 result = IC_RESULT (ic);
6699 aopOp (right, ic, FALSE);
6701 /* if the shift count is known then do it
6702 as efficiently as possible */
6703 if (AOP_TYPE (right) == AOP_LIT)
6705 genRightShiftLiteral (left, right, result, ic, 0);
6709 /* shift count is unknown then we have to form
6710 a loop get the loop count in B : Note: we take
6711 only the lower order byte since shifting
6712 more that 32 bits make no sense anyway, ( the
6713 largest size of an object can be only 32 bits ) */
6715 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6716 emitcode ("inc", "b");
6717 freeAsmop (right, NULL, ic, TRUE);
6718 aopOp (left, ic, FALSE);
6719 aopOp (result, ic, FALSE);
6721 /* now move the left to the result if they are not the
6723 if (!sameRegs (AOP (left), AOP (result)) &&
6724 AOP_SIZE (result) > 1)
6727 size = AOP_SIZE (result);
6731 l = aopGet (AOP (left), offset, FALSE, TRUE);
6732 if (*l == '@' && IS_AOP_PREG (result))
6735 emitcode ("mov", "a,%s", l);
6736 aopPut (AOP (result), "a", offset);
6739 aopPut (AOP (result), l, offset);
6744 tlbl = newiTempLabel (NULL);
6745 tlbl1 = newiTempLabel (NULL);
6746 size = AOP_SIZE (result);
6749 /* if it is only one byte then */
6752 l = aopGet (AOP (left), 0, FALSE, FALSE);
6754 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6755 emitcode ("", "%05d$:", tlbl->key + 100);
6757 emitcode ("rrc", "a");
6758 emitcode ("", "%05d$:", tlbl1->key + 100);
6759 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6760 aopPut (AOP (result), "a", 0);
6764 reAdjustPreg (AOP (result));
6765 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6766 emitcode ("", "%05d$:", tlbl->key + 100);
6770 l = aopGet (AOP (result), offset, FALSE, FALSE);
6772 emitcode ("rrc", "a");
6773 aopPut (AOP (result), "a", offset--);
6775 reAdjustPreg (AOP (result));
6777 emitcode ("", "%05d$:", tlbl1->key + 100);
6778 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6781 freeAsmop (left, NULL, ic, TRUE);
6782 freeAsmop (result, NULL, ic, TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genUnpackBits - generates code for unpacking bits */
6787 /*-----------------------------------------------------------------*/
6789 genUnpackBits (operand * result, char *rname, int ptype)
6797 etype = getSpec (operandType (result));
6798 rsize = getSize (operandType (result));
6799 /* read the first byte */
6805 emitcode ("mov", "a,@%s", rname);
6809 emitcode ("movx", "a,@%s", rname);
6813 emitcode ("movx", "a,@dptr");
6817 emitcode ("clr", "a");
6818 emitcode ("movc", "a,@a+dptr");
6822 emitcode ("lcall", "__gptrget");
6826 rlen = SPEC_BLEN (etype);
6828 /* if we have bitdisplacement then it fits */
6829 /* into this byte completely or if length is */
6830 /* less than a byte */
6831 if ((shCnt = SPEC_BSTR (etype)) ||
6832 (SPEC_BLEN (etype) <= 8))
6835 /* shift right acc */
6838 emitcode ("anl", "a,#0x%02x",
6839 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6840 aopPut (AOP (result), "a", offset++);
6844 /* bit field did not fit in a byte */
6845 aopPut (AOP (result), "a", offset++);
6854 emitcode ("inc", "%s", rname);
6855 emitcode ("mov", "a,@%s", rname);
6859 emitcode ("inc", "%s", rname);
6860 emitcode ("movx", "a,@%s", rname);
6864 emitcode ("inc", "dptr");
6865 emitcode ("movx", "a,@dptr");
6869 emitcode ("clr", "a");
6870 emitcode ("inc", "dptr");
6871 emitcode ("movc", "a,@a+dptr");
6875 emitcode ("inc", "dptr");
6876 emitcode ("lcall", "__gptrget");
6881 /* if we are done */
6885 aopPut (AOP (result), "a", offset++);
6891 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6893 aopPut (AOP (result), "a", offset++);
6901 aopPut (AOP (result), zero, offset++);
6907 /*-----------------------------------------------------------------*/
6908 /* genDataPointerGet - generates code when ptr offset is known */
6909 /*-----------------------------------------------------------------*/
6911 genDataPointerGet (operand * left,
6917 int size, offset = 0;
6918 aopOp (result, ic, TRUE);
6920 /* get the string representation of the name */
6921 l = aopGet (AOP (left), 0, FALSE, TRUE);
6922 size = AOP_SIZE (result);
6926 sprintf (buffer, "(%s + %d)", l + 1, offset);
6928 sprintf (buffer, "%s", l + 1);
6929 aopPut (AOP (result), buffer, offset++);
6932 freeAsmop (left, NULL, ic, TRUE);
6933 freeAsmop (result, NULL, ic, TRUE);
6936 /*-----------------------------------------------------------------*/
6937 /* genNearPointerGet - emitcode for near pointer fetch */
6938 /*-----------------------------------------------------------------*/
6940 genNearPointerGet (operand * left,
6948 sym_link *rtype, *retype;
6949 sym_link *ltype = operandType (left);
6952 rtype = operandType (result);
6953 retype = getSpec (rtype);
6955 aopOp (left, ic, FALSE);
6957 /* if left is rematerialisable and
6958 result is not bit variable type and
6959 the left is pointer to data space i.e
6960 lower 128 bytes of space */
6961 if (AOP_TYPE (left) == AOP_IMMD &&
6962 !IS_BITVAR (retype) &&
6963 DCL_TYPE (ltype) == POINTER)
6965 genDataPointerGet (left, result, ic);
6969 /* if the value is already in a pointer register
6970 then don't need anything more */
6971 if (!AOP_INPREG (AOP (left)))
6973 /* otherwise get a free pointer register */
6975 preg = getFreePtr (ic, &aop, FALSE);
6976 emitcode ("mov", "%s,%s",
6978 aopGet (AOP (left), 0, FALSE, TRUE));
6982 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6984 //aopOp (result, ic, FALSE);
6985 aopOp (result, ic, result?TRUE:FALSE);
6987 /* if bitfield then unpack the bits */
6988 if (IS_BITVAR (retype))
6989 genUnpackBits (result, rname, POINTER);
6992 /* we have can just get the values */
6993 int size = AOP_SIZE (result);
6998 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7001 emitcode ("mov", "a,@%s", rname);
7002 aopPut (AOP (result), "a", offset);
7006 sprintf (buffer, "@%s", rname);
7007 aopPut (AOP (result), buffer, offset);
7011 emitcode ("inc", "%s", rname);
7015 /* now some housekeeping stuff */
7016 if (aop) /* we had to allocate for this iCode */
7018 if (pi) { /* post increment present */
7019 aopPut(AOP ( left ),rname,0);
7021 freeAsmop (NULL, aop, ic, TRUE);
7025 /* we did not allocate which means left
7026 already in a pointer register, then
7027 if size > 0 && this could be used again
7028 we have to point it back to where it
7030 if ((AOP_SIZE (result) > 1 &&
7031 !OP_SYMBOL (left)->remat &&
7032 (OP_SYMBOL (left)->liveTo > ic->seq ||
7036 int size = AOP_SIZE (result) - 1;
7038 emitcode ("dec", "%s", rname);
7043 freeAsmop (left, NULL, ic, TRUE);
7044 freeAsmop (result, NULL, ic, TRUE);
7045 if (pi) pi->generated = 1;
7048 /*-----------------------------------------------------------------*/
7049 /* genPagedPointerGet - emitcode for paged pointer fetch */
7050 /*-----------------------------------------------------------------*/
7052 genPagedPointerGet (operand * left,
7060 sym_link *rtype, *retype;
7062 rtype = operandType (result);
7063 retype = getSpec (rtype);
7065 aopOp (left, ic, FALSE);
7067 /* if the value is already in a pointer register
7068 then don't need anything more */
7069 if (!AOP_INPREG (AOP (left)))
7071 /* otherwise get a free pointer register */
7073 preg = getFreePtr (ic, &aop, FALSE);
7074 emitcode ("mov", "%s,%s",
7076 aopGet (AOP (left), 0, FALSE, TRUE));
7080 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7082 aopOp (result, ic, FALSE);
7084 /* if bitfield then unpack the bits */
7085 if (IS_BITVAR (retype))
7086 genUnpackBits (result, rname, PPOINTER);
7089 /* we have can just get the values */
7090 int size = AOP_SIZE (result);
7096 emitcode ("movx", "a,@%s", rname);
7097 aopPut (AOP (result), "a", offset);
7102 emitcode ("inc", "%s", rname);
7106 /* now some housekeeping stuff */
7107 if (aop) /* we had to allocate for this iCode */
7109 if (pi) aopPut ( AOP (left), rname, 0);
7110 freeAsmop (NULL, aop, ic, TRUE);
7114 /* we did not allocate which means left
7115 already in a pointer register, then
7116 if size > 0 && this could be used again
7117 we have to point it back to where it
7119 if ((AOP_SIZE (result) > 1 &&
7120 !OP_SYMBOL (left)->remat &&
7121 (OP_SYMBOL (left)->liveTo > ic->seq ||
7125 int size = AOP_SIZE (result) - 1;
7127 emitcode ("dec", "%s", rname);
7132 freeAsmop (left, NULL, ic, TRUE);
7133 freeAsmop (result, NULL, ic, TRUE);
7134 if (pi) pi->generated = 1;
7138 /*-----------------------------------------------------------------*/
7139 /* genFarPointerGet - gget value from far space */
7140 /*-----------------------------------------------------------------*/
7142 genFarPointerGet (operand * left,
7143 operand * result, iCode * ic, iCode * pi)
7146 sym_link *retype = getSpec (operandType (result));
7148 aopOp (left, ic, FALSE);
7150 /* if the operand is already in dptr
7151 then we do nothing else we move the value to dptr */
7152 if (AOP_TYPE (left) != AOP_STR)
7154 /* if this is remateriazable */
7155 if (AOP_TYPE (left) == AOP_IMMD)
7156 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7158 { /* we need to get it byte by byte */
7159 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7160 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7163 /* so dptr know contains the address */
7164 aopOp (result, ic, FALSE);
7166 /* if bit then unpack */
7167 if (IS_BITVAR (retype))
7168 genUnpackBits (result, "dptr", FPOINTER);
7171 size = AOP_SIZE (result);
7176 emitcode ("movx", "a,@dptr");
7177 aopPut (AOP (result), "a", offset++);
7179 emitcode ("inc", "dptr");
7183 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7184 aopPut ( AOP (left), "dpl", 0);
7185 aopPut ( AOP (left), "dph", 1);
7188 freeAsmop (left, NULL, ic, TRUE);
7189 freeAsmop (result, NULL, ic, TRUE);
7192 /*-----------------------------------------------------------------*/
7193 /* genCodePointerGet - gget value from code space */
7194 /*-----------------------------------------------------------------*/
7196 genCodePointerGet (operand * left,
7197 operand * result, iCode * ic, iCode *pi)
7200 sym_link *retype = getSpec (operandType (result));
7202 aopOp (left, ic, FALSE);
7204 /* if the operand is already in dptr
7205 then we do nothing else we move the value to dptr */
7206 if (AOP_TYPE (left) != AOP_STR)
7208 /* if this is remateriazable */
7209 if (AOP_TYPE (left) == AOP_IMMD)
7210 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7212 { /* we need to get it byte by byte */
7213 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7214 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7217 /* so dptr know contains the address */
7218 aopOp (result, ic, FALSE);
7220 /* if bit then unpack */
7221 if (IS_BITVAR (retype))
7222 genUnpackBits (result, "dptr", CPOINTER);
7225 size = AOP_SIZE (result);
7230 emitcode ("clr", "a");
7231 emitcode ("movc", "a,@a+dptr");
7232 aopPut (AOP (result), "a", offset++);
7234 emitcode ("inc", "dptr");
7238 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7239 aopPut ( AOP (left), "dpl", 0);
7240 aopPut ( AOP (left), "dph", 1);
7243 freeAsmop (left, NULL, ic, TRUE);
7244 freeAsmop (result, NULL, ic, TRUE);
7247 /*-----------------------------------------------------------------*/
7248 /* genGenPointerGet - gget value from generic pointer space */
7249 /*-----------------------------------------------------------------*/
7251 genGenPointerGet (operand * left,
7252 operand * result, iCode * ic, iCode *pi)
7255 sym_link *retype = getSpec (operandType (result));
7257 aopOp (left, ic, FALSE);
7259 /* if the operand is already in dptr
7260 then we do nothing else we move the value to dptr */
7261 if (AOP_TYPE (left) != AOP_STR)
7263 /* if this is remateriazable */
7264 if (AOP_TYPE (left) == AOP_IMMD)
7266 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7267 emitcode ("mov", "b,#%d", pointerCode (retype));
7270 { /* we need to get it byte by byte */
7271 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7272 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7273 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7276 /* so dptr know contains the address */
7277 aopOp (result, ic, FALSE);
7279 /* if bit then unpack */
7280 if (IS_BITVAR (retype))
7281 genUnpackBits (result, "dptr", GPOINTER);
7284 size = AOP_SIZE (result);
7289 emitcode ("lcall", "__gptrget");
7290 aopPut (AOP (result), "a", offset++);
7292 emitcode ("inc", "dptr");
7296 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7297 aopPut ( AOP (left), "dpl", 0);
7298 aopPut ( AOP (left), "dph", 1);
7301 freeAsmop (left, NULL, ic, TRUE);
7302 freeAsmop (result, NULL, ic, TRUE);
7305 /*-----------------------------------------------------------------*/
7306 /* genPointerGet - generate code for pointer get */
7307 /*-----------------------------------------------------------------*/
7309 genPointerGet (iCode * ic, iCode *pi)
7311 operand *left, *result;
7312 sym_link *type, *etype;
7315 left = IC_LEFT (ic);
7316 result = IC_RESULT (ic);
7318 /* depending on the type of pointer we need to
7319 move it to the correct pointer register */
7320 type = operandType (left);
7321 etype = getSpec (type);
7322 /* if left is of type of pointer then it is simple */
7323 if (IS_PTR (type) && !IS_FUNC (type->next))
7324 p_type = DCL_TYPE (type);
7327 /* we have to go by the storage class */
7328 p_type = PTR_TYPE (SPEC_OCLS (etype));
7331 /* now that we have the pointer type we assign
7332 the pointer values */
7338 genNearPointerGet (left, result, ic, pi);
7342 genPagedPointerGet (left, result, ic, pi);
7346 genFarPointerGet (left, result, ic, pi);
7350 genCodePointerGet (left, result, ic, pi);
7354 genGenPointerGet (left, result, ic, pi);
7360 /*-----------------------------------------------------------------*/
7361 /* genPackBits - generates code for packed bit storage */
7362 /*-----------------------------------------------------------------*/
7364 genPackBits (sym_link * etype,
7366 char *rname, int p_type)
7374 blen = SPEC_BLEN (etype);
7375 bstr = SPEC_BSTR (etype);
7377 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7380 /* if the bit lenth is less than or */
7381 /* it exactly fits a byte then */
7382 if (SPEC_BLEN (etype) <= 8)
7384 shCount = SPEC_BSTR (etype);
7386 /* shift left acc */
7389 if (SPEC_BLEN (etype) < 8)
7390 { /* if smaller than a byte */
7396 emitcode ("mov", "b,a");
7397 emitcode ("mov", "a,@%s", rname);
7401 emitcode ("mov", "b,a");
7402 emitcode ("movx", "a,@dptr");
7406 emitcode ("push", "b");
7407 emitcode ("push", "acc");
7408 emitcode ("lcall", "__gptrget");
7409 emitcode ("pop", "b");
7413 emitcode ("anl", "a,#0x%02x", (unsigned char)
7414 ((unsigned char) (0xFF << (blen + bstr)) |
7415 (unsigned char) (0xFF >> (8 - bstr))));
7416 emitcode ("orl", "a,b");
7417 if (p_type == GPOINTER)
7418 emitcode ("pop", "b");
7425 emitcode ("mov", "@%s,a", rname);
7429 emitcode ("movx", "@dptr,a");
7433 emitcode ("lcall", "__gptrput");
7438 if (SPEC_BLEN (etype) <= 8)
7441 emitcode ("inc", "%s", rname);
7442 rLen = SPEC_BLEN (etype);
7444 /* now generate for lengths greater than one byte */
7448 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7460 emitcode ("mov", "@%s,a", rname);
7463 emitcode ("mov", "@%s,%s", rname, l);
7468 emitcode ("movx", "@dptr,a");
7473 emitcode ("lcall", "__gptrput");
7476 emitcode ("inc", "%s", rname);
7481 /* last last was not complete */
7484 /* save the byte & read byte */
7488 emitcode ("mov", "b,a");
7489 emitcode ("mov", "a,@%s", rname);
7493 emitcode ("mov", "b,a");
7494 emitcode ("movx", "a,@dptr");
7498 emitcode ("push", "b");
7499 emitcode ("push", "acc");
7500 emitcode ("lcall", "__gptrget");
7501 emitcode ("pop", "b");
7505 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7506 emitcode ("orl", "a,b");
7509 if (p_type == GPOINTER)
7510 emitcode ("pop", "b");
7516 emitcode ("mov", "@%s,a", rname);
7520 emitcode ("movx", "@dptr,a");
7524 emitcode ("lcall", "__gptrput");
7528 /*-----------------------------------------------------------------*/
7529 /* genDataPointerSet - remat pointer to data space */
7530 /*-----------------------------------------------------------------*/
7532 genDataPointerSet (operand * right,
7536 int size, offset = 0;
7537 char *l, buffer[256];
7539 aopOp (right, ic, FALSE);
7541 l = aopGet (AOP (result), 0, FALSE, TRUE);
7542 size = AOP_SIZE (right);
7546 sprintf (buffer, "(%s + %d)", l + 1, offset);
7548 sprintf (buffer, "%s", l + 1);
7549 emitcode ("mov", "%s,%s", buffer,
7550 aopGet (AOP (right), offset++, FALSE, FALSE));
7553 freeAsmop (right, NULL, ic, TRUE);
7554 freeAsmop (result, NULL, ic, TRUE);
7557 /*-----------------------------------------------------------------*/
7558 /* genNearPointerSet - emitcode for near pointer put */
7559 /*-----------------------------------------------------------------*/
7561 genNearPointerSet (operand * right,
7569 sym_link *retype, *letype;
7570 sym_link *ptype = operandType (result);
7572 retype = getSpec (operandType (right));
7573 letype = getSpec (ptype);
7574 aopOp (result, ic, FALSE);
7576 /* if the result is rematerializable &
7577 in data space & not a bit variable */
7578 if (AOP_TYPE (result) == AOP_IMMD &&
7579 DCL_TYPE (ptype) == POINTER &&
7580 !IS_BITVAR (retype) &&
7581 !IS_BITVAR (letype))
7583 genDataPointerSet (right, result, ic);
7587 /* if the value is already in a pointer register
7588 then don't need anything more */
7589 if (!AOP_INPREG (AOP (result)))
7591 /* otherwise get a free pointer register */
7593 preg = getFreePtr (ic, &aop, FALSE);
7594 emitcode ("mov", "%s,%s",
7596 aopGet (AOP (result), 0, FALSE, TRUE));
7600 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7602 aopOp (right, ic, FALSE);
7604 /* if bitfield then unpack the bits */
7605 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7606 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7609 /* we have can just get the values */
7610 int size = AOP_SIZE (right);
7615 l = aopGet (AOP (right), offset, FALSE, TRUE);
7619 emitcode ("mov", "@%s,a", rname);
7622 emitcode ("mov", "@%s,%s", rname, l);
7624 emitcode ("inc", "%s", rname);
7629 /* now some housekeeping stuff */
7630 if (aop) /* we had to allocate for this iCode */
7632 if (pi) aopPut (AOP (result),rname,0);
7633 freeAsmop (NULL, aop, ic, TRUE);
7637 /* we did not allocate which means left
7638 already in a pointer register, then
7639 if size > 0 && this could be used again
7640 we have to point it back to where it
7642 if ((AOP_SIZE (right) > 1 &&
7643 !OP_SYMBOL (result)->remat &&
7644 (OP_SYMBOL (result)->liveTo > ic->seq ||
7648 int size = AOP_SIZE (right) - 1;
7650 emitcode ("dec", "%s", rname);
7655 if (pi) pi->generated = 1;
7656 freeAsmop (result, NULL, ic, TRUE);
7657 freeAsmop (right, NULL, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genPagedPointerSet - emitcode for Paged pointer put */
7662 /*-----------------------------------------------------------------*/
7664 genPagedPointerSet (operand * right,
7672 sym_link *retype, *letype;
7674 retype = getSpec (operandType (right));
7675 letype = getSpec (operandType (result));
7677 aopOp (result, ic, FALSE);
7679 /* if the value is already in a pointer register
7680 then don't need anything more */
7681 if (!AOP_INPREG (AOP (result)))
7683 /* otherwise get a free pointer register */
7685 preg = getFreePtr (ic, &aop, FALSE);
7686 emitcode ("mov", "%s,%s",
7688 aopGet (AOP (result), 0, FALSE, TRUE));
7692 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7694 aopOp (right, ic, FALSE);
7696 /* if bitfield then unpack the bits */
7697 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7698 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7701 /* we have can just get the values */
7702 int size = AOP_SIZE (right);
7707 l = aopGet (AOP (right), offset, FALSE, TRUE);
7710 emitcode ("movx", "@%s,a", rname);
7713 emitcode ("inc", "%s", rname);
7719 /* now some housekeeping stuff */
7720 if (aop) /* we had to allocate for this iCode */
7722 if (pi) aopPut (AOP (result),rname,0);
7723 freeAsmop (NULL, aop, ic, TRUE);
7727 /* we did not allocate which means left
7728 already in a pointer register, then
7729 if size > 0 && this could be used again
7730 we have to point it back to where it
7732 if (AOP_SIZE (right) > 1 &&
7733 !OP_SYMBOL (result)->remat &&
7734 (OP_SYMBOL (result)->liveTo > ic->seq ||
7737 int size = AOP_SIZE (right) - 1;
7739 emitcode ("dec", "%s", rname);
7744 if (pi) pi->generated = 1;
7745 freeAsmop (result, NULL, ic, TRUE);
7746 freeAsmop (right, NULL, ic, TRUE);
7751 /*-----------------------------------------------------------------*/
7752 /* genFarPointerSet - set value from far space */
7753 /*-----------------------------------------------------------------*/
7755 genFarPointerSet (operand * right,
7756 operand * result, iCode * ic, iCode * pi)
7759 sym_link *retype = getSpec (operandType (right));
7760 sym_link *letype = getSpec (operandType (result));
7761 aopOp (result, ic, FALSE);
7763 /* if the operand is already in dptr
7764 then we do nothing else we move the value to dptr */
7765 if (AOP_TYPE (result) != AOP_STR)
7767 /* if this is remateriazable */
7768 if (AOP_TYPE (result) == AOP_IMMD)
7769 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7771 { /* we need to get it byte by byte */
7772 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7773 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7776 /* so dptr know contains the address */
7777 aopOp (right, ic, FALSE);
7779 /* if bit then unpack */
7780 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7781 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7784 size = AOP_SIZE (right);
7789 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7791 emitcode ("movx", "@dptr,a");
7793 emitcode ("inc", "dptr");
7796 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7797 aopPut (AOP(result),"dpl",0);
7798 aopPut (AOP(result),"dph",1);
7801 freeAsmop (result, NULL, ic, TRUE);
7802 freeAsmop (right, NULL, ic, TRUE);
7805 /*-----------------------------------------------------------------*/
7806 /* genGenPointerSet - set value from generic pointer space */
7807 /*-----------------------------------------------------------------*/
7809 genGenPointerSet (operand * right,
7810 operand * result, iCode * ic, iCode * pi)
7813 sym_link *retype = getSpec (operandType (right));
7814 sym_link *letype = getSpec (operandType (result));
7816 aopOp (result, ic, FALSE);
7818 /* if the operand is already in dptr
7819 then we do nothing else we move the value to dptr */
7820 if (AOP_TYPE (result) != AOP_STR)
7822 /* if this is remateriazable */
7823 if (AOP_TYPE (result) == AOP_IMMD)
7825 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7826 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7829 { /* we need to get it byte by byte */
7830 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7831 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7832 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7835 /* so dptr know contains the address */
7836 aopOp (right, ic, FALSE);
7838 /* if bit then unpack */
7839 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7840 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7843 size = AOP_SIZE (right);
7848 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7850 emitcode ("lcall", "__gptrput");
7852 emitcode ("inc", "dptr");
7856 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7857 aopPut (AOP(result),"dpl",0);
7858 aopPut (AOP(result),"dph",1);
7861 freeAsmop (result, NULL, ic, TRUE);
7862 freeAsmop (right, NULL, ic, TRUE);
7865 /*-----------------------------------------------------------------*/
7866 /* genPointerSet - stores the value into a pointer location */
7867 /*-----------------------------------------------------------------*/
7869 genPointerSet (iCode * ic, iCode *pi)
7871 operand *right, *result;
7872 sym_link *type, *etype;
7875 right = IC_RIGHT (ic);
7876 result = IC_RESULT (ic);
7878 /* depending on the type of pointer we need to
7879 move it to the correct pointer register */
7880 type = operandType (result);
7881 etype = getSpec (type);
7882 /* if left is of type of pointer then it is simple */
7883 if (IS_PTR (type) && !IS_FUNC (type->next))
7885 p_type = DCL_TYPE (type);
7889 /* we have to go by the storage class */
7890 p_type = PTR_TYPE (SPEC_OCLS (etype));
7893 /* now that we have the pointer type we assign
7894 the pointer values */
7900 genNearPointerSet (right, result, ic, pi);
7904 genPagedPointerSet (right, result, ic, pi);
7908 genFarPointerSet (right, result, ic, pi);
7912 genGenPointerSet (right, result, ic, pi);
7918 /*-----------------------------------------------------------------*/
7919 /* genIfx - generate code for Ifx statement */
7920 /*-----------------------------------------------------------------*/
7922 genIfx (iCode * ic, iCode * popIc)
7924 operand *cond = IC_COND (ic);
7927 aopOp (cond, ic, FALSE);
7929 /* get the value into acc */
7930 if (AOP_TYPE (cond) != AOP_CRY)
7934 /* the result is now in the accumulator */
7935 freeAsmop (cond, NULL, ic, TRUE);
7937 /* if there was something to be popped then do it */
7941 /* if the condition is a bit variable */
7942 if (isbit && IS_ITEMP (cond) &&
7944 genIfxJump (ic, SPIL_LOC (cond)->rname);
7945 else if (isbit && !IS_ITEMP (cond))
7946 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7948 genIfxJump (ic, "a");
7953 /*-----------------------------------------------------------------*/
7954 /* genAddrOf - generates code for address of */
7955 /*-----------------------------------------------------------------*/
7957 genAddrOf (iCode * ic)
7959 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7962 aopOp (IC_RESULT (ic), ic, FALSE);
7964 /* if the operand is on the stack then we
7965 need to get the stack offset of this
7969 /* if it has an offset then we need to compute
7973 emitcode ("mov", "a,_bp");
7974 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7975 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7979 /* we can just move _bp */
7980 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7982 /* fill the result with zero */
7983 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7988 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7994 /* object not on stack then we need the name */
7995 size = AOP_SIZE (IC_RESULT (ic));
8000 char s[SDCC_NAME_MAX];
8002 sprintf (s, "#(%s >> %d)",
8006 sprintf (s, "#%s", sym->rname);
8007 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8011 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8015 /*-----------------------------------------------------------------*/
8016 /* genFarFarAssign - assignment when both are in far space */
8017 /*-----------------------------------------------------------------*/
8019 genFarFarAssign (operand * result, operand * right, iCode * ic)
8021 int size = AOP_SIZE (right);
8024 /* first push the right side on to the stack */
8027 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8029 emitcode ("push", "acc");
8032 freeAsmop (right, NULL, ic, FALSE);
8033 /* now assign DPTR to result */
8034 aopOp (result, ic, FALSE);
8035 size = AOP_SIZE (result);
8038 emitcode ("pop", "acc");
8039 aopPut (AOP (result), "a", --offset);
8041 freeAsmop (result, NULL, ic, FALSE);
8045 /*-----------------------------------------------------------------*/
8046 /* genAssign - generate code for assignment */
8047 /*-----------------------------------------------------------------*/
8049 genAssign (iCode * ic)
8051 operand *result, *right;
8053 unsigned long lit = 0L;
8055 D(emitcode(";","genAssign"));
8057 result = IC_RESULT (ic);
8058 right = IC_RIGHT (ic);
8060 /* if they are the same */
8061 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8064 aopOp (right, ic, FALSE);
8066 /* special case both in far space */
8067 if (AOP_TYPE (right) == AOP_DPTR &&
8068 IS_TRUE_SYMOP (result) &&
8069 isOperandInFarSpace (result))
8072 genFarFarAssign (result, right, ic);
8076 aopOp (result, ic, TRUE);
8078 /* if they are the same registers */
8079 if (sameRegs (AOP (right), AOP (result)))
8082 /* if the result is a bit */
8083 if (AOP_TYPE (result) == AOP_CRY)
8086 /* if the right size is a literal then
8087 we know what the value is */
8088 if (AOP_TYPE (right) == AOP_LIT)
8090 if (((int) operandLitValue (right)))
8091 aopPut (AOP (result), one, 0);
8093 aopPut (AOP (result), zero, 0);
8097 /* the right is also a bit variable */
8098 if (AOP_TYPE (right) == AOP_CRY)
8100 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8101 aopPut (AOP (result), "c", 0);
8107 aopPut (AOP (result), "a", 0);
8111 /* bit variables done */
8113 size = AOP_SIZE (result);
8115 if (AOP_TYPE (right) == AOP_LIT)
8116 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8118 (AOP_TYPE (result) != AOP_REG) &&
8119 (AOP_TYPE (right) == AOP_LIT) &&
8120 !IS_FLOAT (operandType (right)) &&
8123 emitcode ("clr", "a");
8126 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8127 aopPut (AOP (result), "a", size);
8129 aopPut (AOP (result),
8130 aopGet (AOP (right), size, FALSE, FALSE),
8138 aopPut (AOP (result),
8139 aopGet (AOP (right), offset, FALSE, FALSE),
8146 freeAsmop (right, NULL, ic, TRUE);
8147 freeAsmop (result, NULL, ic, TRUE);
8150 /*-----------------------------------------------------------------*/
8151 /* genJumpTab - genrates code for jump table */
8152 /*-----------------------------------------------------------------*/
8154 genJumpTab (iCode * ic)
8159 aopOp (IC_JTCOND (ic), ic, FALSE);
8160 /* get the condition into accumulator */
8161 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8163 /* multiply by three */
8164 emitcode ("add", "a,acc");
8165 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8166 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8168 jtab = newiTempLabel (NULL);
8169 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8170 emitcode ("jmp", "@a+dptr");
8171 emitcode ("", "%05d$:", jtab->key + 100);
8172 /* now generate the jump labels */
8173 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8174 jtab = setNextItem (IC_JTLABELS (ic)))
8175 emitcode ("ljmp", "%05d$", jtab->key + 100);
8179 /*-----------------------------------------------------------------*/
8180 /* genCast - gen code for casting */
8181 /*-----------------------------------------------------------------*/
8183 genCast (iCode * ic)
8185 operand *result = IC_RESULT (ic);
8186 sym_link *ctype = operandType (IC_LEFT (ic));
8187 sym_link *rtype = operandType (IC_RIGHT (ic));
8188 operand *right = IC_RIGHT (ic);
8191 D(emitcode(";", "genCast"));
8193 /* if they are equivalent then do nothing */
8194 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8197 aopOp (right, ic, FALSE);
8198 aopOp (result, ic, FALSE);
8200 /* if the result is a bit */
8201 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8202 if (IS_BITVAR(OP_SYMBOL(result)->type))
8204 /* if the right size is a literal then
8205 we know what the value is */
8206 if (AOP_TYPE (right) == AOP_LIT)
8208 if (((int) operandLitValue (right)))
8209 aopPut (AOP (result), one, 0);
8211 aopPut (AOP (result), zero, 0);
8216 /* the right is also a bit variable */
8217 if (AOP_TYPE (right) == AOP_CRY)
8219 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8220 aopPut (AOP (result), "c", 0);
8226 aopPut (AOP (result), "a", 0);
8230 /* if they are the same size : or less */
8231 if (AOP_SIZE (result) <= AOP_SIZE (right))
8234 /* if they are in the same place */
8235 if (sameRegs (AOP (right), AOP (result)))
8238 /* if they in different places then copy */
8239 size = AOP_SIZE (result);
8243 aopPut (AOP (result),
8244 aopGet (AOP (right), offset, FALSE, FALSE),
8252 /* if the result is of type pointer */
8257 sym_link *type = operandType (right);
8258 sym_link *etype = getSpec (type);
8260 /* pointer to generic pointer */
8261 if (IS_GENPTR (ctype))
8266 p_type = DCL_TYPE (type);
8269 if (SPEC_SCLS(etype)==S_REGISTER) {
8270 // let's assume it is a generic pointer
8273 /* we have to go by the storage class */
8274 p_type = PTR_TYPE (SPEC_OCLS (etype));
8278 /* the first two bytes are known */
8279 size = GPTRSIZE - 1;
8283 aopPut (AOP (result),
8284 aopGet (AOP (right), offset, FALSE, FALSE),
8288 /* the last byte depending on type */
8304 case PPOINTER: // what the fck is this?
8309 /* this should never happen */
8310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8311 "got unknown pointer type");
8314 aopPut (AOP (result), l, GPTRSIZE - 1);
8318 /* just copy the pointers */
8319 size = AOP_SIZE (result);
8323 aopPut (AOP (result),
8324 aopGet (AOP (right), offset, FALSE, FALSE),
8331 /* so we now know that the size of destination is greater
8332 than the size of the source */
8333 /* we move to result for the size of source */
8334 size = AOP_SIZE (right);
8338 aopPut (AOP (result),
8339 aopGet (AOP (right), offset, FALSE, FALSE),
8344 /* now depending on the sign of the source && destination */
8345 size = AOP_SIZE (result) - AOP_SIZE (right);
8346 /* if unsigned or not an integral type */
8347 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8350 aopPut (AOP (result), zero, offset++);
8354 /* we need to extend the sign :{ */
8355 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8358 emitcode ("rlc", "a");
8359 emitcode ("subb", "a,acc");
8361 aopPut (AOP (result), "a", offset++);
8364 /* we are done hurray !!!! */
8367 freeAsmop (right, NULL, ic, TRUE);
8368 freeAsmop (result, NULL, ic, TRUE);
8372 /*-----------------------------------------------------------------*/
8373 /* genDjnz - generate decrement & jump if not zero instrucion */
8374 /*-----------------------------------------------------------------*/
8376 genDjnz (iCode * ic, iCode * ifx)
8382 /* if the if condition has a false label
8383 then we cannot save */
8387 /* if the minus is not of the form
8389 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8390 !IS_OP_LITERAL (IC_RIGHT (ic)))
8393 if (operandLitValue (IC_RIGHT (ic)) != 1)
8396 /* if the size of this greater than one then no
8398 if (getSize (operandType (IC_RESULT (ic))) > 1)
8401 /* otherwise we can save BIG */
8402 lbl = newiTempLabel (NULL);
8403 lbl1 = newiTempLabel (NULL);
8405 aopOp (IC_RESULT (ic), ic, FALSE);
8407 if (AOP_NEEDSACC(IC_RESULT(ic)))
8409 /* If the result is accessed indirectly via
8410 * the accumulator, we must explicitly write
8411 * it back after the decrement.
8413 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8415 if (strcmp(rByte, "a"))
8417 /* Something is hopelessly wrong */
8418 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8419 __FILE__, __LINE__);
8420 /* We can just give up; the generated code will be inefficient,
8423 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8426 emitcode ("dec", "%s", rByte);
8427 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8428 emitcode ("jnz", "%05d$", lbl->key + 100);
8430 else if (IS_AOP_PREG (IC_RESULT (ic)))
8432 emitcode ("dec", "%s",
8433 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8434 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8435 emitcode ("jnz", "%05d$", lbl->key + 100);
8439 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8442 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8443 emitcode ("", "%05d$:", lbl->key + 100);
8444 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8445 emitcode ("", "%05d$:", lbl1->key + 100);
8447 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* genReceive - generate code for a receive iCode */
8454 /*-----------------------------------------------------------------*/
8456 genReceive (iCode * ic)
8458 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8459 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8460 IS_TRUE_SYMOP (IC_RESULT (ic))))
8463 int size = getSize (operandType (IC_RESULT (ic)));
8464 int offset = fReturnSizeMCS51 - size;
8467 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8468 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8471 aopOp (IC_RESULT (ic), ic, FALSE);
8472 size = AOP_SIZE (IC_RESULT (ic));
8476 emitcode ("pop", "acc");
8477 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8484 aopOp (IC_RESULT (ic), ic, FALSE);
8486 assignResultValue (IC_RESULT (ic));
8489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8492 /*-----------------------------------------------------------------*/
8493 /* gen51AggregateAssign - copy complete array's or structures */
8494 /*-----------------------------------------------------------------*/
8495 void gen51AggregateAssign(iCode *ic) {
8496 operand *left=IC_LEFT(ic);
8497 operand *right=IC_RIGHT(ic);
8498 char *fromName=OP_SYMBOL(right)->rname;
8499 char *toName=OP_SYMBOL(left)->rname;
8500 int fromSize=getSize(OP_SYMBOL(right)->type);
8501 int toSize=getSize(OP_SYMBOL(left)->type);
8504 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8505 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8506 // well, this code isn't used yet from anywhere else as for initialising
8507 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8511 if (fromSize!=toSize) {
8512 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8513 ic->filename, ic->lineno);
8518 // use the generic memcpy() for now
8519 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8520 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8521 emitcode ("mov", "a,#%s", fromName);
8522 emitcode ("movx", "@dptr,a");
8523 emitcode ("inc", "dptr");
8524 emitcode ("mov", "a,#(%s>>8)", fromName);
8525 emitcode ("movx", "@dptr,a");
8526 emitcode ("inc", "dptr");
8527 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8528 emitcode ("movx", "@dptr,a");
8529 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8530 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8531 emitcode ("movx", "@dptr,a");
8532 emitcode ("inc", "dptr");
8533 emitcode ("mov", "a,#(%d>>8)", count);
8534 emitcode ("movx", "@dptr,a");
8535 emitcode ("mov", "dptr,#%s", toName);
8536 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8537 emitcode ("lcall", "_memcpy");
8539 // more efficient, but will require the native_memcpy_cs2xs
8540 emitcode ("mov", "r0,#%s", fromName);
8541 emitcode ("mov", "r1,#(%s>>8)", fromName);
8542 emitcode ("mov", "r2,#%s", toName);
8543 emitcode ("mov", "r3,#(%s>>8)", toName);
8544 emitcode ("mov", "r4,#%d", count);
8545 emitcode ("mov", "r5,#(%d>>8)", count);
8546 emitcode ("lcall", "_native_memcpy_cs2xs");
8550 /*-----------------------------------------------------------------*/
8551 /* gen51Code - generate code for 8051 based controllers */
8552 /*-----------------------------------------------------------------*/
8554 gen51Code (iCode * lic)
8559 lineHead = lineCurr = NULL;
8561 /* print the allocation information */
8563 printAllocInfo (currFunc, codeOutFile);
8564 /* if debug information required */
8565 /* if (options.debug && currFunc) { */
8566 if (options.debug && currFunc)
8568 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8570 if (IS_STATIC (currFunc->etype))
8571 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8573 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8576 /* stack pointer name */
8577 if (options.useXstack)
8583 for (ic = lic; ic; ic = ic->next)
8586 if (cln != ic->lineno)
8591 emitcode ("", "C$%s$%d$%d$%d ==.",
8592 FileBaseName (ic->filename), ic->lineno,
8593 ic->level, ic->block);
8596 emitcode (";", "%s %d", ic->filename, ic->lineno);
8599 /* if the result is marked as
8600 spilt and rematerializable or code for
8601 this has already been generated then
8603 if (resultRemat (ic) || ic->generated)
8606 /* depending on the operation */
8626 /* IPOP happens only when trying to restore a
8627 spilt live range, if there is an ifx statement
8628 following this pop then the if statement might
8629 be using some of the registers being popped which
8630 would destory the contents of the register so
8631 we need to check for this condition and handle it */
8633 ic->next->op == IFX &&
8634 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8635 genIfx (ic->next, ic);
8653 genEndFunction (ic);
8673 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8690 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8694 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8701 /* note these two are xlated by algebraic equivalence
8702 during parsing SDCC.y */
8703 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8704 "got '>=' or '<=' shouldn't have come here");
8708 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8720 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8724 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8728 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8755 case GET_VALUE_AT_ADDRESS:
8756 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8760 if (POINTER_SET (ic))
8761 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8787 addSet (&_G.sendSet, ic);
8791 gen51AggregateAssign(ic);
8800 /* now we are ready to call the
8801 peep hole optimizer */
8802 if (!options.nopeep)
8803 peepHole (&lineHead);
8805 /* now do the actual printing */
8806 printLine (lineHead, codeOutFile);