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);
564 /* if the type is a conditional */
565 if (sym->regType == REG_CND)
567 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
572 /* if it is spilt then two situations
574 b) has a spill location */
575 if (sym->isspilt || sym->nRegs == 0)
578 /* rematerialize it NOW */
581 sym->aop = op->aop = aop =
583 aop->size = getSize (sym->type);
590 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
591 aop->size = getSize (sym->type);
592 for (i = 0; i < 2; i++)
593 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; oops");
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 aopOp (IC_LEFT (sic), sic, FALSE);
1863 size = AOP_SIZE (IC_LEFT (sic));
1866 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1868 if (strcmp (l, fReturn[offset]))
1869 emitcode ("mov", "%s,%s",
1874 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1879 /* if we are calling a not _naked function that is not using
1880 the same register bank then we need to save the
1881 destination registers on the stack */
1882 detype = getSpec (operandType (IC_LEFT (ic)));
1883 if (detype && !SPEC_NAKED(detype) &&
1884 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1885 IS_ISR (currFunc->etype))
1889 /* This is unexpected; the bank should have been saved in
1892 saveRBank (SPEC_BANK (detype), ic, FALSE);
1898 /* if caller saves & we have not saved then */
1904 emitcode ("mov", "psw,#0x%02x",
1905 ((SPEC_BANK(detype)) << 3) & 0xff);
1909 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1910 OP_SYMBOL (IC_LEFT (ic))->rname :
1911 OP_SYMBOL (IC_LEFT (ic))->name));
1915 emitcode ("mov", "psw,#0x%02x",
1916 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1919 /* if we need assign a result value */
1920 if ((IS_ITEMP (IC_RESULT (ic)) &&
1921 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1922 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1923 IS_TRUE_SYMOP (IC_RESULT (ic)))
1927 aopOp (IC_RESULT (ic), ic, FALSE);
1930 assignResultValue (IC_RESULT (ic));
1932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1935 /* adjust the stack for parameters if
1940 if (ic->parmBytes > 3)
1942 emitcode ("mov", "a,%s", spname);
1943 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1944 emitcode ("mov", "%s,a", spname);
1947 for (i = 0; i < ic->parmBytes; i++)
1948 emitcode ("dec", "%s", spname);
1951 /* if we hade saved some registers then unsave them */
1952 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1953 unsaveRegisters (ic);
1955 /* if register bank was saved then pop them */
1957 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1960 /*-----------------------------------------------------------------*/
1961 /* genPcall - generates a call by pointer statement */
1962 /*-----------------------------------------------------------------*/
1964 genPcall (iCode * ic)
1967 symbol *rlbl = newiTempLabel (NULL);
1970 /* if caller saves & we have not saved then */
1974 /* if we are calling a function that is not using
1975 the same register bank then we need to save the
1976 destination registers on the stack */
1977 detype = getSpec (operandType (IC_LEFT (ic)));
1979 IS_ISR (currFunc->etype) &&
1980 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1981 saveRBank (SPEC_BANK (detype), ic, TRUE);
1984 /* push the return address on to the stack */
1985 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1986 emitcode ("push", "acc");
1987 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1988 emitcode ("push", "acc");
1990 /* now push the calling address */
1991 aopOp (IC_LEFT (ic), ic, FALSE);
1993 pushSide (IC_LEFT (ic), FPTRSIZE);
1995 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1997 /* if send set is not empty the assign */
2002 for (sic = setFirstItem (_G.sendSet); sic;
2003 sic = setNextItem (_G.sendSet))
2005 int size, offset = 0;
2006 aopOp (IC_LEFT (sic), sic, FALSE);
2007 size = AOP_SIZE (IC_LEFT (sic));
2010 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2012 if (strcmp (l, fReturn[offset]))
2013 emitcode ("mov", "%s,%s",
2018 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2023 emitcode ("ret", "");
2024 emitcode ("", "%05d$:", (rlbl->key + 100));
2027 /* if we need assign a result value */
2028 if ((IS_ITEMP (IC_RESULT (ic)) &&
2029 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2030 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2031 IS_TRUE_SYMOP (IC_RESULT (ic)))
2035 aopOp (IC_RESULT (ic), ic, FALSE);
2038 assignResultValue (IC_RESULT (ic));
2040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2043 /* adjust the stack for parameters if
2048 if (ic->parmBytes > 3)
2050 emitcode ("mov", "a,%s", spname);
2051 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2052 emitcode ("mov", "%s,a", spname);
2055 for (i = 0; i < ic->parmBytes; i++)
2056 emitcode ("dec", "%s", spname);
2060 /* if register bank was saved then unsave them */
2062 (SPEC_BANK (currFunc->etype) !=
2063 SPEC_BANK (detype)))
2064 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2066 /* if we hade saved some registers then
2069 unsaveRegisters (ic);
2073 /*-----------------------------------------------------------------*/
2074 /* resultRemat - result is rematerializable */
2075 /*-----------------------------------------------------------------*/
2077 resultRemat (iCode * ic)
2079 if (SKIP_IC (ic) || ic->op == IFX)
2082 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2084 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2085 if (sym->remat && !POINTER_SET (ic))
2092 #if defined(__BORLANDC__) || defined(_MSC_VER)
2093 #define STRCASECMP stricmp
2095 #define STRCASECMP strcasecmp
2098 /*-----------------------------------------------------------------*/
2099 /* inExcludeList - return 1 if the string is in exclude Reg list */
2100 /*-----------------------------------------------------------------*/
2102 inExcludeList (char *s)
2106 if (options.excludeRegs[i] &&
2107 STRCASECMP (options.excludeRegs[i], "none") == 0)
2110 for (i = 0; options.excludeRegs[i]; i++)
2112 if (options.excludeRegs[i] &&
2113 STRCASECMP (s, options.excludeRegs[i]) == 0)
2119 /*-----------------------------------------------------------------*/
2120 /* genFunction - generated code for function entry */
2121 /*-----------------------------------------------------------------*/
2123 genFunction (iCode * ic)
2127 bool switchedPSW = FALSE;
2130 /* create the function header */
2131 emitcode (";", "-----------------------------------------");
2132 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2133 emitcode (";", "-----------------------------------------");
2135 emitcode ("", "%s:", sym->rname);
2136 fetype = getSpec (operandType (IC_LEFT (ic)));
2138 if (SPEC_NAKED(fetype))
2140 emitcode(";", "naked function: no prologue.");
2144 /* if critical function then turn interrupts off */
2145 if (SPEC_CRTCL (fetype))
2146 emitcode ("clr", "ea");
2148 /* here we need to generate the equates for the
2149 register bank if required */
2150 if (SPEC_BANK (fetype) != rbank)
2154 rbank = SPEC_BANK (fetype);
2155 for (i = 0; i < mcs51_nRegs; i++)
2157 if (strcmp (regs8051[i].base, "0") == 0)
2158 emitcode ("", "%s = 0x%02x",
2160 8 * rbank + regs8051[i].offset);
2162 emitcode ("", "%s = %s + 0x%02x",
2165 8 * rbank + regs8051[i].offset);
2169 /* if this is an interrupt service routine then
2170 save acc, b, dpl, dph */
2171 if (IS_ISR (sym->etype))
2174 if (!inExcludeList ("acc"))
2175 emitcode ("push", "acc");
2176 if (!inExcludeList ("b"))
2177 emitcode ("push", "b");
2178 if (!inExcludeList ("dpl"))
2179 emitcode ("push", "dpl");
2180 if (!inExcludeList ("dph"))
2181 emitcode ("push", "dph");
2182 /* if this isr has no bank i.e. is going to
2183 run with bank 0 , then we need to save more
2185 if (!SPEC_BANK (sym->etype))
2188 /* if this function does not call any other
2189 function then we can be economical and
2190 save only those registers that are used */
2195 /* if any registers used */
2198 /* save the registers used */
2199 for (i = 0; i < sym->regsUsed->size; i++)
2201 if (bitVectBitValue (sym->regsUsed, i) ||
2202 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2203 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2210 /* this function has a function call cannot
2211 determines register usage so we will have to push the
2213 saveRBank (0, ic, FALSE);
2218 /* This ISR uses a non-zero bank.
2220 * We assume that the bank is available for our
2223 * However, if this ISR calls a function which uses some
2224 * other bank, we must save that bank entirely.
2226 unsigned long banksToSave = 0;
2231 #define MAX_REGISTER_BANKS 4
2236 for (i = ic; i; i = i->next)
2238 if (i->op == ENDFUNCTION)
2240 /* we got to the end OK. */
2248 detype = getSpec(operandType (IC_LEFT(i)));
2250 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2252 /* Mark this bank for saving. */
2253 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2255 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2259 banksToSave |= (1 << SPEC_BANK(detype));
2262 /* And note that we don't need to do it in
2270 /* This is a mess; we have no idea what
2271 * register bank the called function might
2274 * The only thing I can think of to do is
2275 * throw a warning and hope.
2277 werror(W_FUNCPTR_IN_USING_ISR);
2281 if (banksToSave && options.useXstack)
2283 /* Since we aren't passing it an ic,
2284 * saveRBank will assume r0 is available to abuse.
2286 * So switch to our (trashable) bank now, so
2287 * the caller's R0 isn't trashed.
2289 emitcode ("push", "psw");
2290 emitcode ("mov", "psw,#0x%02x",
2291 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2295 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2297 if (banksToSave & (1 << ix))
2299 saveRBank(ix, NULL, FALSE);
2303 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2308 /* if callee-save to be used for this function
2309 then save the registers being used in this function */
2310 if (sym->calleeSave)
2314 /* if any registers used */
2317 /* save the registers used */
2318 for (i = 0; i < sym->regsUsed->size; i++)
2320 if (bitVectBitValue (sym->regsUsed, i) ||
2321 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2323 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2331 /* set the register bank to the desired value */
2332 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2335 emitcode ("push", "psw");
2336 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2339 if (IS_RENT (sym->etype) || options.stackAuto)
2342 if (options.useXstack)
2344 emitcode ("mov", "r0,%s", spname);
2345 emitcode ("mov", "a,_bp");
2346 emitcode ("movx", "@r0,a");
2347 emitcode ("inc", "%s", spname);
2351 /* set up the stack */
2352 emitcode ("push", "_bp"); /* save the callers stack */
2354 emitcode ("mov", "_bp,%s", spname);
2357 /* adjust the stack for the function */
2363 werror (W_STACK_OVERFLOW, sym->name);
2365 if (i > 3 && sym->recvSize < 4)
2368 emitcode ("mov", "a,sp");
2369 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2370 emitcode ("mov", "sp,a");
2375 emitcode ("inc", "sp");
2381 emitcode ("mov", "a,_spx");
2382 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2383 emitcode ("mov", "_spx,a");
2388 /*-----------------------------------------------------------------*/
2389 /* genEndFunction - generates epilogue for functions */
2390 /*-----------------------------------------------------------------*/
2392 genEndFunction (iCode * ic)
2394 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2396 if (SPEC_NAKED(sym->etype))
2398 emitcode(";", "naked function: no epilogue.");
2402 if (IS_RENT (sym->etype) || options.stackAuto)
2404 emitcode ("mov", "%s,_bp", spname);
2407 /* if use external stack but some variables were
2408 added to the local stack then decrement the
2410 if (options.useXstack && sym->stack)
2412 emitcode ("mov", "a,sp");
2413 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2414 emitcode ("mov", "sp,a");
2418 if ((IS_RENT (sym->etype) || options.stackAuto))
2420 if (options.useXstack)
2422 emitcode ("mov", "r0,%s", spname);
2423 emitcode ("movx", "a,@r0");
2424 emitcode ("mov", "_bp,a");
2425 emitcode ("dec", "%s", spname);
2429 emitcode ("pop", "_bp");
2433 /* restore the register bank */
2434 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2436 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2437 || !options.useXstack)
2439 /* Special case of ISR using non-zero bank with useXstack
2442 emitcode ("pop", "psw");
2446 if (IS_ISR (sym->etype))
2449 /* now we need to restore the registers */
2450 /* if this isr has no bank i.e. is going to
2451 run with bank 0 , then we need to save more
2453 if (!SPEC_BANK (sym->etype))
2455 /* if this function does not call any other
2456 function then we can be economical and
2457 save only those registers that are used */
2462 /* if any registers used */
2465 /* save the registers used */
2466 for (i = sym->regsUsed->size; i >= 0; i--)
2468 if (bitVectBitValue (sym->regsUsed, i) ||
2469 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2470 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2477 /* this function has a function call cannot
2478 determines register usage so we will have to pop the
2480 unsaveRBank (0, ic, FALSE);
2485 /* This ISR uses a non-zero bank.
2487 * Restore any register banks saved by genFunction
2490 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2493 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2495 if (savedBanks & (1 << ix))
2497 unsaveRBank(ix, NULL, FALSE);
2501 if (options.useXstack)
2503 /* Restore bank AFTER calling unsaveRBank,
2504 * since it can trash r0.
2506 emitcode ("pop", "psw");
2510 if (!inExcludeList ("dph"))
2511 emitcode ("pop", "dph");
2512 if (!inExcludeList ("dpl"))
2513 emitcode ("pop", "dpl");
2514 if (!inExcludeList ("b"))
2515 emitcode ("pop", "b");
2516 if (!inExcludeList ("acc"))
2517 emitcode ("pop", "acc");
2519 if (SPEC_CRTCL (sym->etype))
2520 emitcode ("setb", "ea");
2522 /* if debug then send end of function */
2523 /* if (options.debug && currFunc) */
2524 if (options.debug && currFunc)
2527 emitcode ("", "C$%s$%d$%d$%d ==.",
2528 FileBaseName (ic->filename), currFunc->lastLine,
2529 ic->level, ic->block);
2530 if (IS_STATIC (currFunc->etype))
2531 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2533 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2537 emitcode ("reti", "");
2541 if (SPEC_CRTCL (sym->etype))
2542 emitcode ("setb", "ea");
2544 if (sym->calleeSave)
2548 /* if any registers used */
2551 /* save the registers used */
2552 for (i = sym->regsUsed->size; i >= 0; i--)
2554 if (bitVectBitValue (sym->regsUsed, i) ||
2555 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2556 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2562 /* if debug then send end of function */
2563 if (options.debug && currFunc)
2566 emitcode ("", "C$%s$%d$%d$%d ==.",
2567 FileBaseName (ic->filename), currFunc->lastLine,
2568 ic->level, ic->block);
2569 if (IS_STATIC (currFunc->etype))
2570 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2572 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2576 emitcode ("ret", "");
2581 /*-----------------------------------------------------------------*/
2582 /* genRet - generate code for return statement */
2583 /*-----------------------------------------------------------------*/
2587 int size, offset = 0, pushed = 0;
2589 /* if we have no return value then
2590 just generate the "ret" */
2594 /* we have something to return then
2595 move the return value into place */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2597 size = AOP_SIZE (IC_LEFT (ic));
2602 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2605 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2607 emitcode ("push", "%s", l);
2612 l = aopGet (AOP (IC_LEFT (ic)), offset,
2614 if (strcmp (fReturn[offset], l))
2615 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2624 if (strcmp (fReturn[pushed], "a"))
2625 emitcode ("pop", fReturn[pushed]);
2627 emitcode ("pop", "acc");
2630 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2633 /* generate a jump to the return label
2634 if the next is not the return statement */
2635 if (!(ic->next && ic->next->op == LABEL &&
2636 IC_LABEL (ic->next) == returnLabel))
2638 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2642 /*-----------------------------------------------------------------*/
2643 /* genLabel - generates a label */
2644 /*-----------------------------------------------------------------*/
2646 genLabel (iCode * ic)
2648 /* special case never generate */
2649 if (IC_LABEL (ic) == entryLabel)
2652 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2655 /*-----------------------------------------------------------------*/
2656 /* genGoto - generates a ljmp */
2657 /*-----------------------------------------------------------------*/
2659 genGoto (iCode * ic)
2661 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2664 /*-----------------------------------------------------------------*/
2665 /* findLabelBackwards: walks back through the iCode chain looking */
2666 /* for the given label. Returns number of iCode instructions */
2667 /* between that label and given ic. */
2668 /* Returns zero if label not found. */
2669 /*-----------------------------------------------------------------*/
2671 findLabelBackwards (iCode * ic, int key)
2680 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2682 /* printf("findLabelBackwards = %d\n", count); */
2690 /*-----------------------------------------------------------------*/
2691 /* genPlusIncr :- does addition with increment if possible */
2692 /*-----------------------------------------------------------------*/
2694 genPlusIncr (iCode * ic)
2696 unsigned int icount;
2697 unsigned int size = getDataSize (IC_RESULT (ic));
2699 /* will try to generate an increment */
2700 /* if the right side is not a literal
2702 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2705 /* if the literal value of the right hand side
2706 is greater than 4 then it is not worth it */
2707 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2710 /* if increment 16 bits in register */
2711 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2719 /* If the next instruction is a goto and the goto target
2720 * is < 10 instructions previous to this, we can generate
2721 * jumps straight to that target.
2723 if (ic->next && ic->next->op == GOTO
2724 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2725 && labelRange <= 10)
2727 emitcode (";", "tail increment optimized");
2728 tlbl = IC_LABEL (ic->next);
2733 tlbl = newiTempLabel (NULL);
2736 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2737 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2738 IS_AOP_PREG (IC_RESULT (ic)))
2739 emitcode ("cjne", "%s,#0x00,%05d$"
2740 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2744 emitcode ("clr", "a");
2745 emitcode ("cjne", "a,%s,%05d$"
2746 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2750 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2753 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2754 IS_AOP_PREG (IC_RESULT (ic)))
2755 emitcode ("cjne", "%s,#0x00,%05d$"
2756 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2759 emitcode ("cjne", "a,%s,%05d$"
2760 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2763 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2767 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2768 IS_AOP_PREG (IC_RESULT (ic)))
2769 emitcode ("cjne", "%s,#0x00,%05d$"
2770 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2774 emitcode ("cjne", "a,%s,%05d$"
2775 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2778 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2783 emitcode ("", "%05d$:", tlbl->key + 100);
2788 /* if the sizes are greater than 1 then we cannot */
2789 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2790 AOP_SIZE (IC_LEFT (ic)) > 1)
2793 /* we can if the aops of the left & result match or
2794 if they are in registers and the registers are the
2796 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2801 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2802 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2803 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2809 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2818 /*-----------------------------------------------------------------*/
2819 /* outBitAcc - output a bit in acc */
2820 /*-----------------------------------------------------------------*/
2822 outBitAcc (operand * result)
2824 symbol *tlbl = newiTempLabel (NULL);
2825 /* if the result is a bit */
2826 if (AOP_TYPE (result) == AOP_CRY)
2828 aopPut (AOP (result), "a", 0);
2832 emitcode ("jz", "%05d$", tlbl->key + 100);
2833 emitcode ("mov", "a,%s", one);
2834 emitcode ("", "%05d$:", tlbl->key + 100);
2839 /*-----------------------------------------------------------------*/
2840 /* genPlusBits - generates code for addition of two bits */
2841 /*-----------------------------------------------------------------*/
2843 genPlusBits (iCode * ic)
2845 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2847 symbol *lbl = newiTempLabel (NULL);
2848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2849 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2850 emitcode ("cpl", "c");
2851 emitcode ("", "%05d$:", (lbl->key + 100));
2852 outBitC (IC_RESULT (ic));
2856 emitcode ("clr", "a");
2857 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2858 emitcode ("rlc", "a");
2859 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2860 emitcode ("addc", "a,#0x00");
2861 outAcc (IC_RESULT (ic));
2866 /* This is the original version of this code.
2868 * This is being kept around for reference,
2869 * because I am not entirely sure I got it right...
2872 adjustArithmeticResult (iCode * ic)
2874 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2875 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2876 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2877 aopPut (AOP (IC_RESULT (ic)),
2878 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2881 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2882 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2883 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2884 aopPut (AOP (IC_RESULT (ic)),
2885 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2888 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2889 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2890 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2891 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2892 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2895 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2896 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2900 /* This is the pure and virtuous version of this code.
2901 * I'm pretty certain it's right, but not enough to toss the old
2905 adjustArithmeticResult (iCode * ic)
2907 if (opIsGptr (IC_RESULT (ic)) &&
2908 opIsGptr (IC_LEFT (ic)) &&
2909 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2911 aopPut (AOP (IC_RESULT (ic)),
2912 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2916 if (opIsGptr (IC_RESULT (ic)) &&
2917 opIsGptr (IC_RIGHT (ic)) &&
2918 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2920 aopPut (AOP (IC_RESULT (ic)),
2921 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2925 if (opIsGptr (IC_RESULT (ic)) &&
2926 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2927 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2928 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2932 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2933 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2938 /*-----------------------------------------------------------------*/
2939 /* genPlus - generates code for addition */
2940 /*-----------------------------------------------------------------*/
2942 genPlus (iCode * ic)
2944 int size, offset = 0;
2946 /* special cases :- */
2948 aopOp (IC_LEFT (ic), ic, FALSE);
2949 aopOp (IC_RIGHT (ic), ic, FALSE);
2950 aopOp (IC_RESULT (ic), ic, TRUE);
2952 /* if literal, literal on the right or
2953 if left requires ACC or right is already
2955 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2956 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2957 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2959 operand *t = IC_RIGHT (ic);
2960 IC_RIGHT (ic) = IC_LEFT (ic);
2964 /* if both left & right are in bit
2966 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2967 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2973 /* if left in bit space & right literal */
2974 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2975 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2977 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2978 /* if result in bit space */
2979 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2981 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2982 emitcode ("cpl", "c");
2983 outBitC (IC_RESULT (ic));
2987 size = getDataSize (IC_RESULT (ic));
2990 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2991 emitcode ("addc", "a,#00");
2992 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2998 /* if I can do an increment instead
2999 of add then GOOD for ME */
3000 if (genPlusIncr (ic) == TRUE)
3003 size = getDataSize (IC_RESULT (ic));
3007 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3009 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3011 emitcode ("add", "a,%s",
3012 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3014 emitcode ("addc", "a,%s",
3015 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3019 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3021 emitcode ("add", "a,%s",
3022 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3024 emitcode ("addc", "a,%s",
3025 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3027 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3030 adjustArithmeticResult (ic);
3033 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3034 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3035 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3038 /*-----------------------------------------------------------------*/
3039 /* genMinusDec :- does subtraction with deccrement if possible */
3040 /*-----------------------------------------------------------------*/
3042 genMinusDec (iCode * ic)
3044 unsigned int icount;
3045 unsigned int size = getDataSize (IC_RESULT (ic));
3047 /* will try to generate an increment */
3048 /* if the right side is not a literal
3050 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3053 /* if the literal value of the right hand side
3054 is greater than 4 then it is not worth it */
3055 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3058 /* if decrement 16 bits in register */
3059 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3067 /* If the next instruction is a goto and the goto target
3068 * is <= 10 instructions previous to this, we can generate
3069 * jumps straight to that target.
3071 if (ic->next && ic->next->op == GOTO
3072 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3073 && labelRange <= 10)
3075 emitcode (";", "tail decrement optimized");
3076 tlbl = IC_LABEL (ic->next);
3081 tlbl = newiTempLabel (NULL);
3085 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3086 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3087 IS_AOP_PREG (IC_RESULT (ic)))
3088 emitcode ("cjne", "%s,#0xff,%05d$"
3089 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3093 emitcode ("mov", "a,#0xff");
3094 emitcode ("cjne", "a,%s,%05d$"
3095 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3098 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3101 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3102 IS_AOP_PREG (IC_RESULT (ic)))
3103 emitcode ("cjne", "%s,#0xff,%05d$"
3104 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3108 emitcode ("cjne", "a,%s,%05d$"
3109 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3112 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3116 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3117 IS_AOP_PREG (IC_RESULT (ic)))
3118 emitcode ("cjne", "%s,#0xff,%05d$"
3119 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3123 emitcode ("cjne", "a,%s,%05d$"
3124 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3127 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3131 emitcode ("", "%05d$:", tlbl->key + 100);
3136 /* if the sizes are greater than 1 then we cannot */
3137 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3138 AOP_SIZE (IC_LEFT (ic)) > 1)
3141 /* we can if the aops of the left & result match or
3142 if they are in registers and the registers are the
3144 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3148 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3156 /*-----------------------------------------------------------------*/
3157 /* addSign - complete with sign */
3158 /*-----------------------------------------------------------------*/
3160 addSign (operand * result, int offset, int sign)
3162 int size = (getDataSize (result) - offset);
3167 emitcode ("rlc", "a");
3168 emitcode ("subb", "a,acc");
3170 aopPut (AOP (result), "a", offset++);
3174 aopPut (AOP (result), zero, offset++);
3178 /*-----------------------------------------------------------------*/
3179 /* genMinusBits - generates code for subtraction of two bits */
3180 /*-----------------------------------------------------------------*/
3182 genMinusBits (iCode * ic)
3184 symbol *lbl = newiTempLabel (NULL);
3185 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3187 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3188 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3189 emitcode ("cpl", "c");
3190 emitcode ("", "%05d$:", (lbl->key + 100));
3191 outBitC (IC_RESULT (ic));
3195 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3196 emitcode ("subb", "a,acc");
3197 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3198 emitcode ("inc", "a");
3199 emitcode ("", "%05d$:", (lbl->key + 100));
3200 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3201 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3205 /*-----------------------------------------------------------------*/
3206 /* genMinus - generates code for subtraction */
3207 /*-----------------------------------------------------------------*/
3209 genMinus (iCode * ic)
3211 int size, offset = 0;
3212 unsigned long lit = 0L;
3214 aopOp (IC_LEFT (ic), ic, FALSE);
3215 aopOp (IC_RIGHT (ic), ic, FALSE);
3216 aopOp (IC_RESULT (ic), ic, TRUE);
3218 /* special cases :- */
3219 /* if both left & right are in bit space */
3220 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3221 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3227 /* if I can do an decrement instead
3228 of subtract then GOOD for ME */
3229 if (genMinusDec (ic) == TRUE)
3232 size = getDataSize (IC_RESULT (ic));
3234 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3240 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3244 /* if literal, add a,#-lit, else normal subb */
3247 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3248 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3249 emitcode ("subb", "a,%s",
3250 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3253 /* first add without previous c */
3255 if (!size && lit==-1) {
3256 emitcode ("dec", "a");
3258 emitcode ("add", "a,#0x%02x",
3259 (unsigned int) (lit & 0x0FFL));
3262 emitcode ("addc", "a,#0x%02x",
3263 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3266 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3269 adjustArithmeticResult (ic);
3272 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3273 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3274 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3278 /*-----------------------------------------------------------------*/
3279 /* genMultbits :- multiplication of bits */
3280 /*-----------------------------------------------------------------*/
3282 genMultbits (operand * left,
3286 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3287 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3292 /*-----------------------------------------------------------------*/
3293 /* genMultOneByte : 8*8=8/16 bit multiplication */
3294 /*-----------------------------------------------------------------*/
3296 genMultOneByte (operand * left,
3300 sym_link *opetype = operandType (result);
3302 int size=AOP_SIZE(result);
3304 if (size<1 || size>2) {
3305 // this should never happen
3306 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3307 AOP_SIZE(result), __FILE__, lineno);
3311 /* (if two literals: the value is computed before) */
3312 /* if one literal, literal on the right */
3313 if (AOP_TYPE (left) == AOP_LIT)
3318 //emitcode (";", "swapped left and right");
3321 if (SPEC_USIGN(opetype)
3322 // ignore the sign of left and right, what else can we do?
3323 || (SPEC_USIGN(operandType(left)) &&
3324 SPEC_USIGN(operandType(right)))) {
3325 // just an unsigned 8*8=8/16 multiply
3326 //emitcode (";","unsigned");
3327 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3328 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3329 emitcode ("mul", "ab");
3330 aopPut (AOP (result), "a", 0);
3332 aopPut (AOP (result), "b", 1);
3337 // we have to do a signed multiply
3339 //emitcode (";", "signed");
3340 emitcode ("clr", "F0"); // reset sign flag
3341 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3343 lbl=newiTempLabel(NULL);
3344 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3345 // left side is negative, 8-bit two's complement, this fails for -128
3346 emitcode ("setb", "F0"); // set sign flag
3347 emitcode ("cpl", "a");
3348 emitcode ("inc", "a");
3350 emitcode ("", "%05d$:", lbl->key+100);
3353 if (AOP_TYPE(right)==AOP_LIT) {
3354 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3355 /* AND literal negative */
3357 emitcode ("cpl", "F0"); // complement sign flag
3358 emitcode ("mov", "b,#0x%02x", -val);
3360 emitcode ("mov", "b,#0x%02x", val);
3363 lbl=newiTempLabel(NULL);
3364 emitcode ("mov", "b,a");
3365 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3366 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3367 // right side is negative, 8-bit two's complement
3368 emitcode ("cpl", "F0"); // complement sign flag
3369 emitcode ("cpl", "a");
3370 emitcode ("inc", "a");
3371 emitcode ("", "%05d$:", lbl->key+100);
3373 emitcode ("mul", "ab");
3375 lbl=newiTempLabel(NULL);
3376 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3377 // only ONE op was negative, we have to do a 8/16-bit two's complement
3378 emitcode ("cpl", "a"); // lsb
3380 emitcode ("inc", "a");
3382 emitcode ("add", "a,#1");
3383 emitcode ("xch", "a,b");
3384 emitcode ("cpl", "a"); // msb
3385 emitcode ("addc", "a,#0");
3386 emitcode ("xch", "a,b");
3389 emitcode ("", "%05d$:", lbl->key+100);
3390 aopPut (AOP (result), "a", 0);
3392 aopPut (AOP (result), "b", 1);
3396 /*-----------------------------------------------------------------*/
3397 /* genMult - generates code for multiplication */
3398 /*-----------------------------------------------------------------*/
3400 genMult (iCode * ic)
3402 operand *left = IC_LEFT (ic);
3403 operand *right = IC_RIGHT (ic);
3404 operand *result = IC_RESULT (ic);
3406 /* assign the amsops */
3407 aopOp (left, ic, FALSE);
3408 aopOp (right, ic, FALSE);
3409 aopOp (result, ic, TRUE);
3411 /* special cases first */
3413 if (AOP_TYPE (left) == AOP_CRY &&
3414 AOP_TYPE (right) == AOP_CRY)
3416 genMultbits (left, right, result);
3420 /* if both are of size == 1 */
3421 if (AOP_SIZE (left) == 1 &&
3422 AOP_SIZE (right) == 1)
3424 genMultOneByte (left, right, result);
3428 /* should have been converted to function call */
3432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3434 freeAsmop (result, NULL, ic, TRUE);
3437 /*-----------------------------------------------------------------*/
3438 /* genDivbits :- division of bits */
3439 /*-----------------------------------------------------------------*/
3441 genDivbits (operand * left,
3448 /* the result must be bit */
3449 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3450 l = aopGet (AOP (left), 0, FALSE, FALSE);
3454 emitcode ("div", "ab");
3455 emitcode ("rrc", "a");
3456 aopPut (AOP (result), "c", 0);
3459 /*-----------------------------------------------------------------*/
3460 /* genDivOneByte : 8 bit division */
3461 /*-----------------------------------------------------------------*/
3463 genDivOneByte (operand * left,
3467 sym_link *opetype = operandType (result);
3472 size = AOP_SIZE (result) - 1;
3474 /* signed or unsigned */
3475 if (SPEC_USIGN (opetype))
3477 /* unsigned is easy */
3478 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3479 l = aopGet (AOP (left), 0, FALSE, FALSE);
3481 emitcode ("div", "ab");
3482 aopPut (AOP (result), "a", 0);
3484 aopPut (AOP (result), zero, offset++);
3488 /* signed is a little bit more difficult */
3490 /* save the signs of the operands */
3491 l = aopGet (AOP (left), 0, FALSE, FALSE);
3493 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3494 emitcode ("push", "acc"); /* save it on the stack */
3496 /* now sign adjust for both left & right */
3497 l = aopGet (AOP (right), 0, FALSE, FALSE);
3499 lbl = newiTempLabel (NULL);
3500 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3501 emitcode ("cpl", "a");
3502 emitcode ("inc", "a");
3503 emitcode ("", "%05d$:", (lbl->key + 100));
3504 emitcode ("mov", "b,a");
3506 /* sign adjust left side */
3507 l = aopGet (AOP (left), 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));
3516 /* now the division */
3517 emitcode ("div", "ab");
3518 /* we are interested in the lower order
3520 emitcode ("mov", "b,a");
3521 lbl = newiTempLabel (NULL);
3522 emitcode ("pop", "acc");
3523 /* if there was an over flow we don't
3524 adjust the sign of the result */
3525 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3526 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3528 emitcode ("clr", "a");
3529 emitcode ("subb", "a,b");
3530 emitcode ("mov", "b,a");
3531 emitcode ("", "%05d$:", (lbl->key + 100));
3533 /* now we are done */
3534 aopPut (AOP (result), "b", 0);
3537 emitcode ("mov", "c,b.7");
3538 emitcode ("subb", "a,acc");
3541 aopPut (AOP (result), "a", offset++);
3545 /*-----------------------------------------------------------------*/
3546 /* genDiv - generates code for division */
3547 /*-----------------------------------------------------------------*/
3551 operand *left = IC_LEFT (ic);
3552 operand *right = IC_RIGHT (ic);
3553 operand *result = IC_RESULT (ic);
3555 /* assign the amsops */
3556 aopOp (left, ic, FALSE);
3557 aopOp (right, ic, FALSE);
3558 aopOp (result, ic, TRUE);
3560 /* special cases first */
3562 if (AOP_TYPE (left) == AOP_CRY &&
3563 AOP_TYPE (right) == AOP_CRY)
3565 genDivbits (left, right, result);
3569 /* if both are of size == 1 */
3570 if (AOP_SIZE (left) == 1 &&
3571 AOP_SIZE (right) == 1)
3573 genDivOneByte (left, right, result);
3577 /* should have been converted to function call */
3580 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3581 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3582 freeAsmop (result, NULL, ic, TRUE);
3585 /*-----------------------------------------------------------------*/
3586 /* genModbits :- modulus of bits */
3587 /*-----------------------------------------------------------------*/
3589 genModbits (operand * left,
3596 /* the result must be bit */
3597 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3598 l = aopGet (AOP (left), 0, FALSE, FALSE);
3602 emitcode ("div", "ab");
3603 emitcode ("mov", "a,b");
3604 emitcode ("rrc", "a");
3605 aopPut (AOP (result), "c", 0);
3608 /*-----------------------------------------------------------------*/
3609 /* genModOneByte : 8 bit modulus */
3610 /*-----------------------------------------------------------------*/
3612 genModOneByte (operand * left,
3616 sym_link *opetype = operandType (result);
3620 /* signed or unsigned */
3621 if (SPEC_USIGN (opetype))
3623 /* unsigned is easy */
3624 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3625 l = aopGet (AOP (left), 0, FALSE, FALSE);
3627 emitcode ("div", "ab");
3628 aopPut (AOP (result), "b", 0);
3632 /* signed is a little bit more difficult */
3634 /* save the signs of the operands */
3635 l = aopGet (AOP (left), 0, FALSE, FALSE);
3638 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3639 emitcode ("push", "acc"); /* save it on the stack */
3641 /* now sign adjust for both left & right */
3642 l = aopGet (AOP (right), 0, FALSE, FALSE);
3645 lbl = newiTempLabel (NULL);
3646 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3647 emitcode ("cpl", "a");
3648 emitcode ("inc", "a");
3649 emitcode ("", "%05d$:", (lbl->key + 100));
3650 emitcode ("mov", "b,a");
3652 /* sign adjust left side */
3653 l = aopGet (AOP (left), 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));
3662 /* now the multiplication */
3663 emitcode ("div", "ab");
3664 /* we are interested in the lower order
3666 lbl = newiTempLabel (NULL);
3667 emitcode ("pop", "acc");
3668 /* if there was an over flow we don't
3669 adjust the sign of the result */
3670 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3671 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3673 emitcode ("clr", "a");
3674 emitcode ("subb", "a,b");
3675 emitcode ("mov", "b,a");
3676 emitcode ("", "%05d$:", (lbl->key + 100));
3678 /* now we are done */
3679 aopPut (AOP (result), "b", 0);
3683 /*-----------------------------------------------------------------*/
3684 /* genMod - generates code for division */
3685 /*-----------------------------------------------------------------*/
3689 operand *left = IC_LEFT (ic);
3690 operand *right = IC_RIGHT (ic);
3691 operand *result = IC_RESULT (ic);
3693 /* assign the amsops */
3694 aopOp (left, ic, FALSE);
3695 aopOp (right, ic, FALSE);
3696 aopOp (result, ic, TRUE);
3698 /* special cases first */
3700 if (AOP_TYPE (left) == AOP_CRY &&
3701 AOP_TYPE (right) == AOP_CRY)
3703 genModbits (left, right, result);
3707 /* if both are of size == 1 */
3708 if (AOP_SIZE (left) == 1 &&
3709 AOP_SIZE (right) == 1)
3711 genModOneByte (left, right, result);
3715 /* should have been converted to function call */
3719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3721 freeAsmop (result, NULL, ic, TRUE);
3724 /*-----------------------------------------------------------------*/
3725 /* genIfxJump :- will create a jump depending on the ifx */
3726 /*-----------------------------------------------------------------*/
3728 genIfxJump (iCode * ic, char *jval)
3731 symbol *tlbl = newiTempLabel (NULL);
3734 /* if true label then we jump if condition
3738 jlbl = IC_TRUE (ic);
3739 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3740 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3744 /* false label is present */
3745 jlbl = IC_FALSE (ic);
3746 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3747 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3749 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3750 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3752 emitcode (inst, "%05d$", tlbl->key + 100);
3753 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3754 emitcode ("", "%05d$:", tlbl->key + 100);
3756 /* mark the icode as generated */
3760 /*-----------------------------------------------------------------*/
3761 /* genCmp :- greater or less than comparison */
3762 /*-----------------------------------------------------------------*/
3764 genCmp (operand * left, operand * right,
3765 operand * result, iCode * ifx, int sign, iCode *ic)
3767 int size, offset = 0;
3768 unsigned long lit = 0L;
3770 /* if left & right are bit variables */
3771 if (AOP_TYPE (left) == AOP_CRY &&
3772 AOP_TYPE (right) == AOP_CRY)
3774 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3775 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3779 /* subtract right from left if at the
3780 end the carry flag is set then we know that
3781 left is greater than right */
3782 size = max (AOP_SIZE (left), AOP_SIZE (right));
3784 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3785 if ((size == 1) && !sign &&
3786 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3788 symbol *lbl = newiTempLabel (NULL);
3789 emitcode ("cjne", "%s,%s,%05d$",
3790 aopGet (AOP (left), offset, FALSE, FALSE),
3791 aopGet (AOP (right), offset, FALSE, FALSE),
3793 emitcode ("", "%05d$:", lbl->key + 100);
3797 if (AOP_TYPE (right) == AOP_LIT)
3799 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3800 /* optimize if(x < 0) or if(x >= 0) */
3809 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3810 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3812 genIfxJump (ifx, "acc.7");
3816 emitcode ("rlc", "a");
3824 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3825 if (sign && size == 0)
3827 emitcode ("xrl", "a,#0x80");
3828 if (AOP_TYPE (right) == AOP_LIT)
3830 unsigned long lit = (unsigned long)
3831 floatFromVal (AOP (right)->aopu.aop_lit);
3832 emitcode ("subb", "a,#0x%02x",
3833 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3837 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3838 emitcode ("xrl", "b,#0x80");
3839 emitcode ("subb", "a,b");
3843 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3851 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3857 /* if the result is used in the next
3858 ifx conditional branch then generate
3859 code a little differently */
3861 genIfxJump (ifx, "c");
3864 /* leave the result in acc */
3868 /*-----------------------------------------------------------------*/
3869 /* genCmpGt :- greater than comparison */
3870 /*-----------------------------------------------------------------*/
3872 genCmpGt (iCode * ic, iCode * ifx)
3874 operand *left, *right, *result;
3875 sym_link *letype, *retype;
3878 left = IC_LEFT (ic);
3879 right = IC_RIGHT (ic);
3880 result = IC_RESULT (ic);
3882 letype = getSpec (operandType (left));
3883 retype = getSpec (operandType (right));
3884 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3885 /* assign the amsops */
3886 aopOp (left, ic, FALSE);
3887 aopOp (right, ic, FALSE);
3888 aopOp (result, ic, TRUE);
3890 genCmp (right, left, result, ifx, sign,ic);
3892 freeAsmop (result, NULL, ic, TRUE);
3895 /*-----------------------------------------------------------------*/
3896 /* genCmpLt - less than comparisons */
3897 /*-----------------------------------------------------------------*/
3899 genCmpLt (iCode * ic, iCode * ifx)
3901 operand *left, *right, *result;
3902 sym_link *letype, *retype;
3905 left = IC_LEFT (ic);
3906 right = IC_RIGHT (ic);
3907 result = IC_RESULT (ic);
3909 letype = getSpec (operandType (left));
3910 retype = getSpec (operandType (right));
3911 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3913 /* assign the amsops */
3914 aopOp (left, ic, FALSE);
3915 aopOp (right, ic, FALSE);
3916 aopOp (result, ic, TRUE);
3918 genCmp (left, right, result, ifx, sign,ic);
3920 freeAsmop (result, NULL, ic, TRUE);
3923 /*-----------------------------------------------------------------*/
3924 /* gencjneshort - compare and jump if not equal */
3925 /*-----------------------------------------------------------------*/
3927 gencjneshort (operand * left, operand * right, symbol * lbl)
3929 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3931 unsigned long lit = 0L;
3933 /* if the left side is a literal or
3934 if the right is in a pointer register and left
3936 if ((AOP_TYPE (left) == AOP_LIT) ||
3937 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3943 if (AOP_TYPE (right) == AOP_LIT)
3944 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3946 /* if the right side is a literal then anything goes */
3947 if (AOP_TYPE (right) == AOP_LIT &&
3948 AOP_TYPE (left) != AOP_DIR)
3952 emitcode ("cjne", "%s,%s,%05d$",
3953 aopGet (AOP (left), offset, FALSE, FALSE),
3954 aopGet (AOP (right), offset, FALSE, FALSE),
3960 /* if the right side is in a register or in direct space or
3961 if the left is a pointer register & right is not */
3962 else if (AOP_TYPE (right) == AOP_REG ||
3963 AOP_TYPE (right) == AOP_DIR ||
3964 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3965 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3969 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3970 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3971 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3972 emitcode ("jnz", "%05d$", lbl->key + 100);
3974 emitcode ("cjne", "a,%s,%05d$",
3975 aopGet (AOP (right), offset, FALSE, TRUE),
3982 /* right is a pointer reg need both a & b */
3985 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3986 if (strcmp (l, "b"))
3987 emitcode ("mov", "b,%s", l);
3988 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3989 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3995 /*-----------------------------------------------------------------*/
3996 /* gencjne - compare and jump if not equal */
3997 /*-----------------------------------------------------------------*/
3999 gencjne (operand * left, operand * right, symbol * lbl)
4001 symbol *tlbl = newiTempLabel (NULL);
4003 gencjneshort (left, right, lbl);
4005 emitcode ("mov", "a,%s", one);
4006 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4007 emitcode ("", "%05d$:", lbl->key + 100);
4008 emitcode ("clr", "a");
4009 emitcode ("", "%05d$:", tlbl->key + 100);
4012 /*-----------------------------------------------------------------*/
4013 /* genCmpEq - generates code for equal to */
4014 /*-----------------------------------------------------------------*/
4016 genCmpEq (iCode * ic, iCode * ifx)
4018 operand *left, *right, *result;
4020 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4021 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4022 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4024 /* if literal, literal on the right or
4025 if the right is in a pointer register and left
4027 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4028 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4030 operand *t = IC_RIGHT (ic);
4031 IC_RIGHT (ic) = IC_LEFT (ic);
4035 if (ifx && !AOP_SIZE (result))
4038 /* if they are both bit variables */
4039 if (AOP_TYPE (left) == AOP_CRY &&
4040 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4042 if (AOP_TYPE (right) == AOP_LIT)
4044 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4048 emitcode ("cpl", "c");
4052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056 emitcode ("clr", "c");
4058 /* AOP_TYPE(right) == AOP_CRY */
4062 symbol *lbl = newiTempLabel (NULL);
4063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4064 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4065 emitcode ("cpl", "c");
4066 emitcode ("", "%05d$:", (lbl->key + 100));
4068 /* if true label then we jump if condition
4070 tlbl = newiTempLabel (NULL);
4073 emitcode ("jnc", "%05d$", tlbl->key + 100);
4074 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4078 emitcode ("jc", "%05d$", tlbl->key + 100);
4079 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4081 emitcode ("", "%05d$:", tlbl->key + 100);
4085 tlbl = newiTempLabel (NULL);
4086 gencjneshort (left, right, tlbl);
4089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4090 emitcode ("", "%05d$:", tlbl->key + 100);
4094 symbol *lbl = newiTempLabel (NULL);
4095 emitcode ("sjmp", "%05d$", lbl->key + 100);
4096 emitcode ("", "%05d$:", tlbl->key + 100);
4097 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4098 emitcode ("", "%05d$:", lbl->key + 100);
4101 /* mark the icode as generated */
4106 /* if they are both bit variables */
4107 if (AOP_TYPE (left) == AOP_CRY &&
4108 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4110 if (AOP_TYPE (right) == AOP_LIT)
4112 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4116 emitcode ("cpl", "c");
4120 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4124 emitcode ("clr", "c");
4126 /* AOP_TYPE(right) == AOP_CRY */
4130 symbol *lbl = newiTempLabel (NULL);
4131 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4132 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4133 emitcode ("cpl", "c");
4134 emitcode ("", "%05d$:", (lbl->key + 100));
4137 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4144 genIfxJump (ifx, "c");
4147 /* if the result is used in an arithmetic operation
4148 then put the result in place */
4153 gencjne (left, right, newiTempLabel (NULL));
4154 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4156 aopPut (AOP (result), "a", 0);
4161 genIfxJump (ifx, "a");
4164 /* if the result is used in an arithmetic operation
4165 then put the result in place */
4166 if (AOP_TYPE (result) != AOP_CRY)
4168 /* leave the result in acc */
4172 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4173 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4174 freeAsmop (result, NULL, ic, TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* ifxForOp - returns the icode containing the ifx for operand */
4179 /*-----------------------------------------------------------------*/
4181 ifxForOp (operand * op, iCode * ic)
4183 /* if true symbol then needs to be assigned */
4184 if (IS_TRUE_SYMOP (op))
4187 /* if this has register type condition and
4188 the next instruction is ifx with the same operand
4189 and live to of the operand is upto the ifx only then */
4191 ic->next->op == IFX &&
4192 IC_COND (ic->next)->key == op->key &&
4193 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4199 /*-----------------------------------------------------------------*/
4200 /* hasInc - operand is incremented before any other use */
4201 /*-----------------------------------------------------------------*/
4203 hasInc (operand *op, iCode *ic)
4205 sym_link *type = operandType(op);
4206 sym_link *retype = getSpec (type);
4207 iCode *lic = ic->next;
4210 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4211 isize = getSize(type->next);
4213 /* if operand of the form op = op + <sizeof *op> */
4214 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4215 isOperandEqual(IC_RESULT(lic),op) &&
4216 isOperandLiteral(IC_RIGHT(lic)) &&
4217 operandLitValue(IC_RIGHT(lic)) == isize) {
4220 /* if the operand used or deffed */
4221 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4229 /*-----------------------------------------------------------------*/
4230 /* genAndOp - for && operation */
4231 /*-----------------------------------------------------------------*/
4233 genAndOp (iCode * ic)
4235 operand *left, *right, *result;
4238 /* note here that && operations that are in an
4239 if statement are taken away by backPatchLabels
4240 only those used in arthmetic operations remain */
4241 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4242 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4243 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4245 /* if both are bit variables */
4246 if (AOP_TYPE (left) == AOP_CRY &&
4247 AOP_TYPE (right) == AOP_CRY)
4249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4250 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4255 tlbl = newiTempLabel (NULL);
4257 emitcode ("jz", "%05d$", tlbl->key + 100);
4259 emitcode ("", "%05d$:", tlbl->key + 100);
4263 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4265 freeAsmop (result, NULL, ic, TRUE);
4269 /*-----------------------------------------------------------------*/
4270 /* genOrOp - for || operation */
4271 /*-----------------------------------------------------------------*/
4273 genOrOp (iCode * ic)
4275 operand *left, *right, *result;
4278 /* note here that || operations that are in an
4279 if statement are taken away by backPatchLabels
4280 only those used in arthmetic operations remain */
4281 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4282 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4283 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4285 /* if both are bit variables */
4286 if (AOP_TYPE (left) == AOP_CRY &&
4287 AOP_TYPE (right) == AOP_CRY)
4289 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4290 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4295 tlbl = newiTempLabel (NULL);
4297 emitcode ("jnz", "%05d$", tlbl->key + 100);
4299 emitcode ("", "%05d$:", tlbl->key + 100);
4303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4304 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4305 freeAsmop (result, NULL, ic, TRUE);
4308 /*-----------------------------------------------------------------*/
4309 /* isLiteralBit - test if lit == 2^n */
4310 /*-----------------------------------------------------------------*/
4312 isLiteralBit (unsigned long lit)
4314 unsigned long pw[32] =
4315 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4316 0x100L, 0x200L, 0x400L, 0x800L,
4317 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4318 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4319 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4320 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4321 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4324 for (idx = 0; idx < 32; idx++)
4330 /*-----------------------------------------------------------------*/
4331 /* continueIfTrue - */
4332 /*-----------------------------------------------------------------*/
4334 continueIfTrue (iCode * ic)
4337 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4341 /*-----------------------------------------------------------------*/
4343 /*-----------------------------------------------------------------*/
4345 jumpIfTrue (iCode * ic)
4348 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4352 /*-----------------------------------------------------------------*/
4353 /* jmpTrueOrFalse - */
4354 /*-----------------------------------------------------------------*/
4356 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4358 // ugly but optimized by peephole
4361 symbol *nlbl = newiTempLabel (NULL);
4362 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4363 emitcode ("", "%05d$:", tlbl->key + 100);
4364 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4365 emitcode ("", "%05d$:", nlbl->key + 100);
4369 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4370 emitcode ("", "%05d$:", tlbl->key + 100);
4375 /*-----------------------------------------------------------------*/
4376 /* genAnd - code for and */
4377 /*-----------------------------------------------------------------*/
4379 genAnd (iCode * ic, iCode * ifx)
4381 operand *left, *right, *result;
4382 int size, offset = 0;
4383 unsigned long lit = 0L;
4387 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4388 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4389 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4392 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4394 AOP_TYPE (left), AOP_TYPE (right));
4395 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4397 AOP_SIZE (left), AOP_SIZE (right));
4400 /* if left is a literal & right is not then exchange them */
4401 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4402 AOP_NEEDSACC (left))
4404 operand *tmp = right;
4409 /* if result = right then exchange them */
4410 if (sameRegs (AOP (result), AOP (right)))
4412 operand *tmp = right;
4417 /* if right is bit then exchange them */
4418 if (AOP_TYPE (right) == AOP_CRY &&
4419 AOP_TYPE (left) != AOP_CRY)
4421 operand *tmp = right;
4425 if (AOP_TYPE (right) == AOP_LIT)
4426 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4428 size = AOP_SIZE (result);
4431 // result = bit & yy;
4432 if (AOP_TYPE (left) == AOP_CRY)
4434 // c = bit & literal;
4435 if (AOP_TYPE (right) == AOP_LIT)
4439 if (size && sameRegs (AOP (result), AOP (left)))
4442 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4447 if (size && (AOP_TYPE (result) == AOP_CRY))
4449 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4452 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4457 emitcode ("clr", "c");
4462 if (AOP_TYPE (right) == AOP_CRY)
4465 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4466 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4471 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4473 emitcode ("rrc", "a");
4474 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4482 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4483 genIfxJump (ifx, "c");
4487 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4488 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4489 if ((AOP_TYPE (right) == AOP_LIT) &&
4490 (AOP_TYPE (result) == AOP_CRY) &&
4491 (AOP_TYPE (left) != AOP_CRY))
4493 int posbit = isLiteralBit (lit);
4498 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4501 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4507 sprintf (buffer, "acc.%d", posbit & 0x07);
4508 genIfxJump (ifx, buffer);
4515 symbol *tlbl = newiTempLabel (NULL);
4516 int sizel = AOP_SIZE (left);
4518 emitcode ("setb", "c");
4521 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4523 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4525 if ((posbit = isLiteralBit (bytelit)) != 0)
4526 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4529 if (bytelit != 0x0FFL)
4530 emitcode ("anl", "a,%s",
4531 aopGet (AOP (right), offset, FALSE, TRUE));
4532 emitcode ("jnz", "%05d$", tlbl->key + 100);
4537 // bit = left & literal
4540 emitcode ("clr", "c");
4541 emitcode ("", "%05d$:", tlbl->key + 100);
4543 // if(left & literal)
4547 jmpTrueOrFalse (ifx, tlbl);
4555 /* if left is same as result */
4556 if (sameRegs (AOP (result), AOP (left)))
4558 for (; size--; offset++)
4560 if (AOP_TYPE (right) == AOP_LIT)
4562 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4564 else if (bytelit == 0)
4565 aopPut (AOP (result), zero, offset);
4566 else if (IS_AOP_PREG (result))
4568 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4569 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4570 aopPut (AOP (result), "a", offset);
4573 emitcode ("anl", "%s,%s",
4574 aopGet (AOP (left), offset, FALSE, TRUE),
4575 aopGet (AOP (right), offset, FALSE, FALSE));
4579 if (AOP_TYPE (left) == AOP_ACC)
4580 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4583 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4584 if (IS_AOP_PREG (result))
4586 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4587 aopPut (AOP (result), "a", offset);
4591 emitcode ("anl", "%s,a",
4592 aopGet (AOP (left), offset, FALSE, TRUE));
4599 // left & result in different registers
4600 if (AOP_TYPE (result) == AOP_CRY)
4603 // if(size), result in bit
4604 // if(!size && ifx), conditional oper: if(left & right)
4605 symbol *tlbl = newiTempLabel (NULL);
4606 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4608 emitcode ("setb", "c");
4611 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4612 emitcode ("anl", "a,%s",
4613 aopGet (AOP (right), offset, FALSE, FALSE));
4615 if (AOP_TYPE(left)==AOP_ACC) {
4616 emitcode("mov", "b,a");
4617 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4618 emitcode("anl", "a,b");
4620 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4621 emitcode ("anl", "a,%s",
4622 aopGet (AOP (left), offset, FALSE, FALSE));
4625 emitcode ("jnz", "%05d$", tlbl->key + 100);
4631 emitcode ("", "%05d$:", tlbl->key + 100);
4635 jmpTrueOrFalse (ifx, tlbl);
4639 for (; (size--); offset++)
4642 // result = left & right
4643 if (AOP_TYPE (right) == AOP_LIT)
4645 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4647 aopPut (AOP (result),
4648 aopGet (AOP (left), offset, FALSE, FALSE),
4652 else if (bytelit == 0)
4654 aopPut (AOP (result), zero, offset);
4658 // faster than result <- left, anl result,right
4659 // and better if result is SFR
4660 if (AOP_TYPE (left) == AOP_ACC)
4661 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4665 emitcode ("anl", "a,%s",
4666 aopGet (AOP (left), offset, FALSE, FALSE));
4668 aopPut (AOP (result), "a", offset);
4674 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4675 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4676 freeAsmop (result, NULL, ic, TRUE);
4679 /*-----------------------------------------------------------------*/
4680 /* genOr - code for or */
4681 /*-----------------------------------------------------------------*/
4683 genOr (iCode * ic, iCode * ifx)
4685 operand *left, *right, *result;
4686 int size, offset = 0;
4687 unsigned long lit = 0L;
4689 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4690 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4691 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4694 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4696 AOP_TYPE (left), AOP_TYPE (right));
4697 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4699 AOP_SIZE (left), AOP_SIZE (right));
4702 /* if left is a literal & right is not then exchange them */
4703 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4704 AOP_NEEDSACC (left))
4706 operand *tmp = right;
4711 /* if result = right then exchange them */
4712 if (sameRegs (AOP (result), AOP (right)))
4714 operand *tmp = right;
4719 /* if right is bit then exchange them */
4720 if (AOP_TYPE (right) == AOP_CRY &&
4721 AOP_TYPE (left) != AOP_CRY)
4723 operand *tmp = right;
4727 if (AOP_TYPE (right) == AOP_LIT)
4728 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4730 size = AOP_SIZE (result);
4734 if (AOP_TYPE (left) == AOP_CRY)
4736 if (AOP_TYPE (right) == AOP_LIT)
4738 // c = bit & literal;
4741 // lit != 0 => result = 1
4742 if (AOP_TYPE (result) == AOP_CRY)
4745 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4747 continueIfTrue (ifx);
4750 emitcode ("setb", "c");
4754 // lit == 0 => result = left
4755 if (size && sameRegs (AOP (result), AOP (left)))
4757 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4762 if (AOP_TYPE (right) == AOP_CRY)
4765 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4766 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4771 symbol *tlbl = newiTempLabel (NULL);
4772 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4773 emitcode ("setb", "c");
4774 emitcode ("jb", "%s,%05d$",
4775 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4777 emitcode ("jnz", "%05d$", tlbl->key + 100);
4778 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4780 jmpTrueOrFalse (ifx, tlbl);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4795 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4796 genIfxJump (ifx, "c");
4800 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4801 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4802 if ((AOP_TYPE (right) == AOP_LIT) &&
4803 (AOP_TYPE (result) == AOP_CRY) &&
4804 (AOP_TYPE (left) != AOP_CRY))
4810 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4812 continueIfTrue (ifx);
4817 // lit = 0, result = boolean(left)
4819 emitcode ("setb", "c");
4823 symbol *tlbl = newiTempLabel (NULL);
4824 emitcode ("jnz", "%05d$", tlbl->key + 100);
4826 emitcode ("", "%05d$:", tlbl->key + 100);
4830 genIfxJump (ifx, "a");
4838 /* if left is same as result */
4839 if (sameRegs (AOP (result), AOP (left)))
4841 for (; size--; offset++)
4843 if (AOP_TYPE (right) == AOP_LIT)
4845 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4847 else if (IS_AOP_PREG (left))
4849 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4850 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4851 aopPut (AOP (result), "a", offset);
4854 emitcode ("orl", "%s,%s",
4855 aopGet (AOP (left), offset, FALSE, TRUE),
4856 aopGet (AOP (right), offset, FALSE, FALSE));
4860 if (AOP_TYPE (left) == AOP_ACC)
4861 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4864 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4865 if (IS_AOP_PREG (left))
4867 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4868 aopPut (AOP (result), "a", offset);
4871 emitcode ("orl", "%s,a",
4872 aopGet (AOP (left), offset, FALSE, TRUE));
4879 // left & result in different registers
4880 if (AOP_TYPE (result) == AOP_CRY)
4883 // if(size), result in bit
4884 // if(!size && ifx), conditional oper: if(left | right)
4885 symbol *tlbl = newiTempLabel (NULL);
4886 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4888 emitcode ("setb", "c");
4891 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4892 emitcode ("orl", "a,%s",
4893 aopGet (AOP (right), offset, FALSE, FALSE));
4895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4896 emitcode ("orl", "a,%s",
4897 aopGet (AOP (left), offset, FALSE, FALSE));
4899 emitcode ("jnz", "%05d$", tlbl->key + 100);
4905 emitcode ("", "%05d$:", tlbl->key + 100);
4909 jmpTrueOrFalse (ifx, tlbl);
4912 for (; (size--); offset++)
4915 // result = left & right
4916 if (AOP_TYPE (right) == AOP_LIT)
4918 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4920 aopPut (AOP (result),
4921 aopGet (AOP (left), offset, FALSE, FALSE),
4926 // faster than result <- left, anl result,right
4927 // and better if result is SFR
4928 if (AOP_TYPE (left) == AOP_ACC)
4929 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4933 emitcode ("orl", "a,%s",
4934 aopGet (AOP (left), offset, FALSE, FALSE));
4936 aopPut (AOP (result), "a", offset);
4941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genXor - code for xclusive or */
4948 /*-----------------------------------------------------------------*/
4950 genXor (iCode * ic, iCode * ifx)
4952 operand *left, *right, *result;
4953 int size, offset = 0;
4954 unsigned long lit = 0L;
4956 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4957 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4958 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4961 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4963 AOP_TYPE (left), AOP_TYPE (right));
4964 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4966 AOP_SIZE (left), AOP_SIZE (right));
4969 /* if left is a literal & right is not ||
4970 if left needs acc & right does not */
4971 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4972 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4974 operand *tmp = right;
4979 /* if result = right then exchange them */
4980 if (sameRegs (AOP (result), AOP (right)))
4982 operand *tmp = right;
4987 /* if right is bit then exchange them */
4988 if (AOP_TYPE (right) == AOP_CRY &&
4989 AOP_TYPE (left) != AOP_CRY)
4991 operand *tmp = right;
4995 if (AOP_TYPE (right) == AOP_LIT)
4996 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4998 size = AOP_SIZE (result);
5002 if (AOP_TYPE (left) == AOP_CRY)
5004 if (AOP_TYPE (right) == AOP_LIT)
5006 // c = bit & literal;
5009 // lit>>1 != 0 => result = 1
5010 if (AOP_TYPE (result) == AOP_CRY)
5013 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5015 continueIfTrue (ifx);
5018 emitcode ("setb", "c");
5025 // lit == 0, result = left
5026 if (size && sameRegs (AOP (result), AOP (left)))
5028 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5032 // lit == 1, result = not(left)
5033 if (size && sameRegs (AOP (result), AOP (left)))
5035 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5041 emitcode ("cpl", "c");
5050 symbol *tlbl = newiTempLabel (NULL);
5051 if (AOP_TYPE (right) == AOP_CRY)
5054 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5058 int sizer = AOP_SIZE (right);
5060 // if val>>1 != 0, result = 1
5061 emitcode ("setb", "c");
5064 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5066 // test the msb of the lsb
5067 emitcode ("anl", "a,#0xfe");
5068 emitcode ("jnz", "%05d$", tlbl->key + 100);
5072 emitcode ("rrc", "a");
5074 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5075 emitcode ("cpl", "c");
5076 emitcode ("", "%05d$:", (tlbl->key + 100));
5083 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5084 genIfxJump (ifx, "c");
5088 if (sameRegs (AOP (result), AOP (left)))
5090 /* if left is same as result */
5091 for (; size--; offset++)
5093 if (AOP_TYPE (right) == AOP_LIT)
5095 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5097 else if (IS_AOP_PREG (left))
5099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5100 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5101 aopPut (AOP (result), "a", offset);
5104 emitcode ("xrl", "%s,%s",
5105 aopGet (AOP (left), offset, FALSE, TRUE),
5106 aopGet (AOP (right), offset, FALSE, FALSE));
5110 if (AOP_TYPE (left) == AOP_ACC)
5111 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5115 if (IS_AOP_PREG (left))
5117 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5118 aopPut (AOP (result), "a", offset);
5121 emitcode ("xrl", "%s,a",
5122 aopGet (AOP (left), offset, FALSE, TRUE));
5129 // left & result in different registers
5130 if (AOP_TYPE (result) == AOP_CRY)
5133 // if(size), result in bit
5134 // if(!size && ifx), conditional oper: if(left ^ right)
5135 symbol *tlbl = newiTempLabel (NULL);
5136 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5138 emitcode ("setb", "c");
5141 if ((AOP_TYPE (right) == AOP_LIT) &&
5142 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5144 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5148 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5149 emitcode ("xrl", "a,%s",
5150 aopGet (AOP (right), offset, FALSE, FALSE));
5152 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5153 emitcode ("xrl", "a,%s",
5154 aopGet (AOP (left), offset, FALSE, FALSE));
5157 emitcode ("jnz", "%05d$", tlbl->key + 100);
5163 emitcode ("", "%05d$:", tlbl->key + 100);
5167 jmpTrueOrFalse (ifx, tlbl);
5170 for (; (size--); offset++)
5173 // result = left & right
5174 if (AOP_TYPE (right) == AOP_LIT)
5176 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5178 aopPut (AOP (result),
5179 aopGet (AOP (left), offset, FALSE, FALSE),
5184 // faster than result <- left, anl result,right
5185 // and better if result is SFR
5186 if (AOP_TYPE (left) == AOP_ACC)
5187 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5190 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5191 emitcode ("xrl", "a,%s",
5192 aopGet (AOP (left), offset, FALSE, TRUE));
5194 aopPut (AOP (result), "a", offset);
5199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (result, NULL, ic, TRUE);
5204 /*-----------------------------------------------------------------*/
5205 /* genInline - write the inline code out */
5206 /*-----------------------------------------------------------------*/
5208 genInline (iCode * ic)
5210 char *buffer, *bp, *bp1;
5212 _G.inLine += (!options.asmpeep);
5214 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5215 strcpy (buffer, IC_INLINE (ic));
5217 /* emit each line as a code */
5242 /* emitcode("",buffer); */
5243 _G.inLine -= (!options.asmpeep);
5246 /*-----------------------------------------------------------------*/
5247 /* genRRC - rotate right with carry */
5248 /*-----------------------------------------------------------------*/
5252 operand *left, *result;
5253 int size, offset = 0;
5256 /* rotate right with carry */
5257 left = IC_LEFT (ic);
5258 result = IC_RESULT (ic);
5259 aopOp (left, ic, FALSE);
5260 aopOp (result, ic, FALSE);
5262 /* move it to the result */
5263 size = AOP_SIZE (result);
5268 l = aopGet (AOP (left), offset, FALSE, FALSE);
5270 emitcode ("rrc", "a");
5271 if (AOP_SIZE (result) > 1)
5272 aopPut (AOP (result), "a", offset--);
5274 /* now we need to put the carry into the
5275 highest order byte of the result */
5276 if (AOP_SIZE (result) > 1)
5278 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5281 emitcode ("mov", "acc.7,c");
5282 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5283 freeAsmop (left, NULL, ic, TRUE);
5284 freeAsmop (result, NULL, ic, TRUE);
5287 /*-----------------------------------------------------------------*/
5288 /* genRLC - generate code for rotate left with carry */
5289 /*-----------------------------------------------------------------*/
5293 operand *left, *result;
5294 int size, offset = 0;
5297 /* rotate right with carry */
5298 left = IC_LEFT (ic);
5299 result = IC_RESULT (ic);
5300 aopOp (left, ic, FALSE);
5301 aopOp (result, ic, FALSE);
5303 /* move it to the result */
5304 size = AOP_SIZE (result);
5308 l = aopGet (AOP (left), offset, FALSE, FALSE);
5310 emitcode ("add", "a,acc");
5311 if (AOP_SIZE (result) > 1)
5312 aopPut (AOP (result), "a", offset++);
5315 l = aopGet (AOP (left), offset, FALSE, FALSE);
5317 emitcode ("rlc", "a");
5318 if (AOP_SIZE (result) > 1)
5319 aopPut (AOP (result), "a", offset++);
5322 /* now we need to put the carry into the
5323 highest order byte of the result */
5324 if (AOP_SIZE (result) > 1)
5326 l = aopGet (AOP (result), 0, FALSE, FALSE);
5329 emitcode ("mov", "acc.0,c");
5330 aopPut (AOP (result), "a", 0);
5331 freeAsmop (left, NULL, ic, TRUE);
5332 freeAsmop (result, NULL, ic, TRUE);
5335 /*-----------------------------------------------------------------*/
5336 /* genGetHbit - generates code get highest order bit */
5337 /*-----------------------------------------------------------------*/
5339 genGetHbit (iCode * ic)
5341 operand *left, *result;
5342 left = IC_LEFT (ic);
5343 result = IC_RESULT (ic);
5344 aopOp (left, ic, FALSE);
5345 aopOp (result, ic, FALSE);
5347 /* get the highest order byte into a */
5348 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5349 if (AOP_TYPE (result) == AOP_CRY)
5351 emitcode ("rlc", "a");
5356 emitcode ("rl", "a");
5357 emitcode ("anl", "a,#0x01");
5362 freeAsmop (left, NULL, ic, TRUE);
5363 freeAsmop (result, NULL, ic, TRUE);
5366 /*-----------------------------------------------------------------*/
5367 /* AccRol - rotate left accumulator by known count */
5368 /*-----------------------------------------------------------------*/
5370 AccRol (int shCount)
5372 shCount &= 0x0007; // shCount : 0..7
5379 emitcode ("rl", "a");
5382 emitcode ("rl", "a");
5383 emitcode ("rl", "a");
5386 emitcode ("swap", "a");
5387 emitcode ("rr", "a");
5390 emitcode ("swap", "a");
5393 emitcode ("swap", "a");
5394 emitcode ("rl", "a");
5397 emitcode ("rr", "a");
5398 emitcode ("rr", "a");
5401 emitcode ("rr", "a");
5406 /*-----------------------------------------------------------------*/
5407 /* AccLsh - left shift accumulator by known count */
5408 /*-----------------------------------------------------------------*/
5410 AccLsh (int shCount)
5415 emitcode ("add", "a,acc");
5416 else if (shCount == 2)
5418 emitcode ("add", "a,acc");
5419 emitcode ("add", "a,acc");
5423 /* rotate left accumulator */
5425 /* and kill the lower order bits */
5426 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5431 /*-----------------------------------------------------------------*/
5432 /* AccRsh - right shift accumulator by known count */
5433 /*-----------------------------------------------------------------*/
5435 AccRsh (int shCount)
5442 emitcode ("rrc", "a");
5446 /* rotate right accumulator */
5447 AccRol (8 - shCount);
5448 /* and kill the higher order bits */
5449 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5454 /*-----------------------------------------------------------------*/
5455 /* AccSRsh - signed right shift accumulator by known count */
5456 /*-----------------------------------------------------------------*/
5458 AccSRsh (int shCount)
5465 emitcode ("mov", "c,acc.7");
5466 emitcode ("rrc", "a");
5468 else if (shCount == 2)
5470 emitcode ("mov", "c,acc.7");
5471 emitcode ("rrc", "a");
5472 emitcode ("mov", "c,acc.7");
5473 emitcode ("rrc", "a");
5477 tlbl = newiTempLabel (NULL);
5478 /* rotate right accumulator */
5479 AccRol (8 - shCount);
5480 /* and kill the higher order bits */
5481 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5482 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5483 emitcode ("orl", "a,#0x%02x",
5484 (unsigned char) ~SRMask[shCount]);
5485 emitcode ("", "%05d$:", tlbl->key + 100);
5490 /*-----------------------------------------------------------------*/
5491 /* shiftR1Left2Result - shift right one byte from left to result */
5492 /*-----------------------------------------------------------------*/
5494 shiftR1Left2Result (operand * left, int offl,
5495 operand * result, int offr,
5496 int shCount, int sign)
5498 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5499 /* shift right accumulator */
5504 aopPut (AOP (result), "a", offr);
5507 /*-----------------------------------------------------------------*/
5508 /* shiftL1Left2Result - shift left one byte from left to result */
5509 /*-----------------------------------------------------------------*/
5511 shiftL1Left2Result (operand * left, int offl,
5512 operand * result, int offr, int shCount)
5515 l = aopGet (AOP (left), offl, FALSE, FALSE);
5517 /* shift left accumulator */
5519 aopPut (AOP (result), "a", offr);
5522 /*-----------------------------------------------------------------*/
5523 /* movLeft2Result - move byte from left to result */
5524 /*-----------------------------------------------------------------*/
5526 movLeft2Result (operand * left, int offl,
5527 operand * result, int offr, int sign)
5530 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5532 l = aopGet (AOP (left), offl, FALSE, FALSE);
5534 if (*l == '@' && (IS_AOP_PREG (result)))
5536 emitcode ("mov", "a,%s", l);
5537 aopPut (AOP (result), "a", offr);
5542 aopPut (AOP (result), l, offr);
5545 /* MSB sign in acc.7 ! */
5546 if (getDataSize (left) == offl + 1)
5548 emitcode ("mov", "a,%s", l);
5549 aopPut (AOP (result), "a", offr);
5556 /*-----------------------------------------------------------------*/
5557 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5558 /*-----------------------------------------------------------------*/
5562 emitcode ("rrc", "a");
5563 emitcode ("xch", "a,%s", x);
5564 emitcode ("rrc", "a");
5565 emitcode ("xch", "a,%s", x);
5568 /*-----------------------------------------------------------------*/
5569 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5570 /*-----------------------------------------------------------------*/
5574 emitcode ("xch", "a,%s", x);
5575 emitcode ("rlc", "a");
5576 emitcode ("xch", "a,%s", x);
5577 emitcode ("rlc", "a");
5580 /*-----------------------------------------------------------------*/
5581 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5582 /*-----------------------------------------------------------------*/
5586 emitcode ("xch", "a,%s", x);
5587 emitcode ("add", "a,acc");
5588 emitcode ("xch", "a,%s", x);
5589 emitcode ("rlc", "a");
5592 /*-----------------------------------------------------------------*/
5593 /* AccAXLsh - left shift a:x by known count (0..7) */
5594 /*-----------------------------------------------------------------*/
5596 AccAXLsh (char *x, int shCount)
5611 case 5: // AAAAABBB:CCCCCDDD
5613 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5615 emitcode ("anl", "a,#0x%02x",
5616 SLMask[shCount]); // BBB00000:CCCCCDDD
5618 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5620 AccRol (shCount); // DDDCCCCC:BBB00000
5622 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5624 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5626 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5628 emitcode ("anl", "a,#0x%02x",
5629 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5631 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5633 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5636 case 6: // AAAAAABB:CCCCCCDD
5637 emitcode ("anl", "a,#0x%02x",
5638 SRMask[shCount]); // 000000BB:CCCCCCDD
5639 emitcode ("mov", "c,acc.0"); // c = B
5640 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5642 AccAXRrl1 (x); // BCCCCCCD:D000000B
5643 AccAXRrl1 (x); // BBCCCCCC:DD000000
5645 emitcode("rrc","a");
5646 emitcode("xch","a,%s", x);
5647 emitcode("rrc","a");
5648 emitcode("mov","c,acc.0"); //<< get correct bit
5649 emitcode("xch","a,%s", x);
5651 emitcode("rrc","a");
5652 emitcode("xch","a,%s", x);
5653 emitcode("rrc","a");
5654 emitcode("xch","a,%s", x);
5657 case 7: // a:x <<= 7
5659 emitcode ("anl", "a,#0x%02x",
5660 SRMask[shCount]); // 0000000B:CCCCCCCD
5662 emitcode ("mov", "c,acc.0"); // c = B
5664 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5666 AccAXRrl1 (x); // BCCCCCCC:D0000000
5674 /*-----------------------------------------------------------------*/
5675 /* AccAXRsh - right shift a:x known count (0..7) */
5676 /*-----------------------------------------------------------------*/
5678 AccAXRsh (char *x, int shCount)
5686 AccAXRrl1 (x); // 0->a:x
5691 AccAXRrl1 (x); // 0->a:x
5694 AccAXRrl1 (x); // 0->a:x
5699 case 5: // AAAAABBB:CCCCCDDD = a:x
5701 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5703 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5705 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5707 emitcode ("anl", "a,#0x%02x",
5708 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5710 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5712 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5714 emitcode ("anl", "a,#0x%02x",
5715 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5717 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5719 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5721 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5724 case 6: // AABBBBBB:CCDDDDDD
5726 emitcode ("mov", "c,acc.7");
5727 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5729 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5731 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5733 emitcode ("anl", "a,#0x%02x",
5734 SRMask[shCount]); // 000000AA:BBBBBBCC
5737 case 7: // ABBBBBBB:CDDDDDDD
5739 emitcode ("mov", "c,acc.7"); // c = A
5741 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5743 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5745 emitcode ("anl", "a,#0x%02x",
5746 SRMask[shCount]); // 0000000A:BBBBBBBC
5754 /*-----------------------------------------------------------------*/
5755 /* AccAXRshS - right shift signed a:x known count (0..7) */
5756 /*-----------------------------------------------------------------*/
5758 AccAXRshS (char *x, int shCount)
5766 emitcode ("mov", "c,acc.7");
5767 AccAXRrl1 (x); // s->a:x
5771 emitcode ("mov", "c,acc.7");
5772 AccAXRrl1 (x); // s->a:x
5774 emitcode ("mov", "c,acc.7");
5775 AccAXRrl1 (x); // s->a:x
5780 case 5: // AAAAABBB:CCCCCDDD = a:x
5782 tlbl = newiTempLabel (NULL);
5783 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5785 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5787 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5789 emitcode ("anl", "a,#0x%02x",
5790 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5792 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5794 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5796 emitcode ("anl", "a,#0x%02x",
5797 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5799 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5801 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5803 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5805 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5806 emitcode ("orl", "a,#0x%02x",
5807 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5809 emitcode ("", "%05d$:", tlbl->key + 100);
5810 break; // SSSSAAAA:BBBCCCCC
5812 case 6: // AABBBBBB:CCDDDDDD
5814 tlbl = newiTempLabel (NULL);
5815 emitcode ("mov", "c,acc.7");
5816 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5818 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5820 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5822 emitcode ("anl", "a,#0x%02x",
5823 SRMask[shCount]); // 000000AA:BBBBBBCC
5825 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5826 emitcode ("orl", "a,#0x%02x",
5827 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5829 emitcode ("", "%05d$:", tlbl->key + 100);
5831 case 7: // ABBBBBBB:CDDDDDDD
5833 tlbl = newiTempLabel (NULL);
5834 emitcode ("mov", "c,acc.7"); // c = A
5836 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5838 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5840 emitcode ("anl", "a,#0x%02x",
5841 SRMask[shCount]); // 0000000A:BBBBBBBC
5843 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5844 emitcode ("orl", "a,#0x%02x",
5845 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5847 emitcode ("", "%05d$:", tlbl->key + 100);
5854 /*-----------------------------------------------------------------*/
5855 /* shiftL2Left2Result - shift left two bytes from left to result */
5856 /*-----------------------------------------------------------------*/
5858 shiftL2Left2Result (operand * left, int offl,
5859 operand * result, int offr, int shCount)
5861 if (sameRegs (AOP (result), AOP (left)) &&
5862 ((offl + MSB16) == offr))
5864 /* don't crash result[offr] */
5865 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5866 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5870 movLeft2Result (left, offl, result, offr, 0);
5871 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5873 /* ax << shCount (x = lsb(result)) */
5874 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5875 aopPut (AOP (result), "a", offr + MSB16);
5879 /*-----------------------------------------------------------------*/
5880 /* shiftR2Left2Result - shift right two bytes from left to result */
5881 /*-----------------------------------------------------------------*/
5883 shiftR2Left2Result (operand * left, int offl,
5884 operand * result, int offr,
5885 int shCount, int sign)
5887 if (sameRegs (AOP (result), AOP (left)) &&
5888 ((offl + MSB16) == offr))
5890 /* don't crash result[offr] */
5891 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5892 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5896 movLeft2Result (left, offl, result, offr, 0);
5897 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5899 /* a:x >> shCount (x = lsb(result)) */
5901 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5903 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5904 if (getDataSize (result) > 1)
5905 aopPut (AOP (result), "a", offr + MSB16);
5908 /*-----------------------------------------------------------------*/
5909 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5910 /*-----------------------------------------------------------------*/
5912 shiftLLeftOrResult (operand * left, int offl,
5913 operand * result, int offr, int shCount)
5915 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5916 /* shift left accumulator */
5918 /* or with result */
5919 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5920 /* back to result */
5921 aopPut (AOP (result), "a", offr);
5924 /*-----------------------------------------------------------------*/
5925 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5926 /*-----------------------------------------------------------------*/
5928 shiftRLeftOrResult (operand * left, int offl,
5929 operand * result, int offr, int shCount)
5931 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5932 /* shift right accumulator */
5934 /* or with result */
5935 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5936 /* back to result */
5937 aopPut (AOP (result), "a", offr);
5940 /*-----------------------------------------------------------------*/
5941 /* genlshOne - left shift a one byte quantity by known count */
5942 /*-----------------------------------------------------------------*/
5944 genlshOne (operand * result, operand * left, int shCount)
5946 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5949 /*-----------------------------------------------------------------*/
5950 /* genlshTwo - left shift two bytes by known amount != 0 */
5951 /*-----------------------------------------------------------------*/
5953 genlshTwo (operand * result, operand * left, int shCount)
5957 size = getDataSize (result);
5959 /* if shCount >= 8 */
5967 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5969 movLeft2Result (left, LSB, result, MSB16, 0);
5971 aopPut (AOP (result), zero, LSB);
5974 /* 1 <= shCount <= 7 */
5978 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5980 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5984 /*-----------------------------------------------------------------*/
5985 /* shiftLLong - shift left one long from left to result */
5986 /* offl = LSB or MSB16 */
5987 /*-----------------------------------------------------------------*/
5989 shiftLLong (operand * left, operand * result, int offr)
5992 int size = AOP_SIZE (result);
5994 if (size >= LSB + offr)
5996 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5998 emitcode ("add", "a,acc");
5999 if (sameRegs (AOP (left), AOP (result)) &&
6000 size >= MSB16 + offr && offr != LSB)
6001 emitcode ("xch", "a,%s",
6002 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6004 aopPut (AOP (result), "a", LSB + offr);
6007 if (size >= MSB16 + offr)
6009 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6011 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6014 emitcode ("rlc", "a");
6015 if (sameRegs (AOP (left), AOP (result)) &&
6016 size >= MSB24 + offr && offr != LSB)
6017 emitcode ("xch", "a,%s",
6018 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6020 aopPut (AOP (result), "a", MSB16 + offr);
6023 if (size >= MSB24 + offr)
6025 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6027 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6030 emitcode ("rlc", "a");
6031 if (sameRegs (AOP (left), AOP (result)) &&
6032 size >= MSB32 + offr && offr != LSB)
6033 emitcode ("xch", "a,%s",
6034 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6036 aopPut (AOP (result), "a", MSB24 + offr);
6039 if (size > MSB32 + offr)
6041 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6043 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6046 emitcode ("rlc", "a");
6047 aopPut (AOP (result), "a", MSB32 + offr);
6050 aopPut (AOP (result), zero, LSB);
6053 /*-----------------------------------------------------------------*/
6054 /* genlshFour - shift four byte by a known amount != 0 */
6055 /*-----------------------------------------------------------------*/
6057 genlshFour (operand * result, operand * left, int shCount)
6061 size = AOP_SIZE (result);
6063 /* if shifting more that 3 bytes */
6068 /* lowest order of left goes to the highest
6069 order of the destination */
6070 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6072 movLeft2Result (left, LSB, result, MSB32, 0);
6073 aopPut (AOP (result), zero, LSB);
6074 aopPut (AOP (result), zero, MSB16);
6075 aopPut (AOP (result), zero, MSB24);
6079 /* more than two bytes */
6080 else if (shCount >= 16)
6082 /* lower order two bytes goes to higher order two bytes */
6084 /* if some more remaining */
6086 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6089 movLeft2Result (left, MSB16, result, MSB32, 0);
6090 movLeft2Result (left, LSB, result, MSB24, 0);
6092 aopPut (AOP (result), zero, MSB16);
6093 aopPut (AOP (result), zero, LSB);
6097 /* if more than 1 byte */
6098 else if (shCount >= 8)
6100 /* lower order three bytes goes to higher order three bytes */
6105 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6107 movLeft2Result (left, LSB, result, MSB16, 0);
6113 movLeft2Result (left, MSB24, result, MSB32, 0);
6114 movLeft2Result (left, MSB16, result, MSB24, 0);
6115 movLeft2Result (left, LSB, result, MSB16, 0);
6116 aopPut (AOP (result), zero, LSB);
6118 else if (shCount == 1)
6119 shiftLLong (left, result, MSB16);
6122 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6123 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6124 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6125 aopPut (AOP (result), zero, LSB);
6130 /* 1 <= shCount <= 7 */
6131 else if (shCount <= 2)
6133 shiftLLong (left, result, LSB);
6135 shiftLLong (result, result, LSB);
6137 /* 3 <= shCount <= 7, optimize */
6140 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6141 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6142 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6146 /*-----------------------------------------------------------------*/
6147 /* genLeftShiftLiteral - left shifting by known count */
6148 /*-----------------------------------------------------------------*/
6150 genLeftShiftLiteral (operand * left,
6155 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6158 freeAsmop (right, NULL, ic, TRUE);
6160 aopOp (left, ic, FALSE);
6161 aopOp (result, ic, FALSE);
6163 size = getSize (operandType (result));
6166 emitcode ("; shift left ", "result %d, left %d", size,
6170 /* I suppose that the left size >= result size */
6175 movLeft2Result (left, size, result, size, 0);
6179 else if (shCount >= (size * 8))
6181 aopPut (AOP (result), zero, size);
6187 genlshOne (result, left, shCount);
6191 genlshTwo (result, left, shCount);
6195 genlshFour (result, left, shCount);
6198 fprintf(stderr, "*** ack! mystery literal shift!\n");
6202 freeAsmop (left, NULL, ic, TRUE);
6203 freeAsmop (result, NULL, ic, TRUE);
6206 /*-----------------------------------------------------------------*/
6207 /* genLeftShift - generates code for left shifting */
6208 /*-----------------------------------------------------------------*/
6210 genLeftShift (iCode * ic)
6212 operand *left, *right, *result;
6215 symbol *tlbl, *tlbl1;
6217 right = IC_RIGHT (ic);
6218 left = IC_LEFT (ic);
6219 result = IC_RESULT (ic);
6221 aopOp (right, ic, FALSE);
6223 /* if the shift count is known then do it
6224 as efficiently as possible */
6225 if (AOP_TYPE (right) == AOP_LIT)
6227 genLeftShiftLiteral (left, right, result, ic);
6231 /* shift count is unknown then we have to form
6232 a loop get the loop count in B : Note: we take
6233 only the lower order byte since shifting
6234 more that 32 bits make no sense anyway, ( the
6235 largest size of an object can be only 32 bits ) */
6237 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6238 emitcode ("inc", "b");
6239 freeAsmop (right, NULL, ic, TRUE);
6240 aopOp (left, ic, FALSE);
6241 aopOp (result, ic, FALSE);
6243 /* now move the left to the result if they are not the
6245 if (!sameRegs (AOP (left), AOP (result)) &&
6246 AOP_SIZE (result) > 1)
6249 size = AOP_SIZE (result);
6253 l = aopGet (AOP (left), offset, FALSE, TRUE);
6254 if (*l == '@' && (IS_AOP_PREG (result)))
6257 emitcode ("mov", "a,%s", l);
6258 aopPut (AOP (result), "a", offset);
6261 aopPut (AOP (result), l, offset);
6266 tlbl = newiTempLabel (NULL);
6267 size = AOP_SIZE (result);
6269 tlbl1 = newiTempLabel (NULL);
6271 /* if it is only one byte then */
6274 symbol *tlbl1 = newiTempLabel (NULL);
6276 l = aopGet (AOP (left), 0, FALSE, FALSE);
6278 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6279 emitcode ("", "%05d$:", tlbl->key + 100);
6280 emitcode ("add", "a,acc");
6281 emitcode ("", "%05d$:", tlbl1->key + 100);
6282 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6283 aopPut (AOP (result), "a", 0);
6287 reAdjustPreg (AOP (result));
6289 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6290 emitcode ("", "%05d$:", tlbl->key + 100);
6291 l = aopGet (AOP (result), offset, FALSE, FALSE);
6293 emitcode ("add", "a,acc");
6294 aopPut (AOP (result), "a", offset++);
6297 l = aopGet (AOP (result), offset, FALSE, FALSE);
6299 emitcode ("rlc", "a");
6300 aopPut (AOP (result), "a", offset++);
6302 reAdjustPreg (AOP (result));
6304 emitcode ("", "%05d$:", tlbl1->key + 100);
6305 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6307 freeAsmop (left, NULL, ic, TRUE);
6308 freeAsmop (result, NULL, ic, TRUE);
6311 /*-----------------------------------------------------------------*/
6312 /* genrshOne - right shift a one byte quantity by known count */
6313 /*-----------------------------------------------------------------*/
6315 genrshOne (operand * result, operand * left,
6316 int shCount, int sign)
6318 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6321 /*-----------------------------------------------------------------*/
6322 /* genrshTwo - right shift two bytes by known amount != 0 */
6323 /*-----------------------------------------------------------------*/
6325 genrshTwo (operand * result, operand * left,
6326 int shCount, int sign)
6328 /* if shCount >= 8 */
6333 shiftR1Left2Result (left, MSB16, result, LSB,
6336 movLeft2Result (left, MSB16, result, LSB, sign);
6337 addSign (result, MSB16, sign);
6340 /* 1 <= shCount <= 7 */
6342 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6345 /*-----------------------------------------------------------------*/
6346 /* shiftRLong - shift right one long from left to result */
6347 /* offl = LSB or MSB16 */
6348 /*-----------------------------------------------------------------*/
6350 shiftRLong (operand * left, int offl,
6351 operand * result, int sign)
6353 int isSameRegs=sameRegs(AOP(left),AOP(result));
6355 if (isSameRegs && offl>1) {
6356 // we are in big trouble, but this shouldn't happen
6357 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6360 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6365 emitcode ("rlc", "a");
6366 emitcode ("subb", "a,acc");
6367 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6369 aopPut (AOP(result), zero, MSB32);
6374 emitcode ("clr", "c");
6376 emitcode ("mov", "c,acc.7");
6379 emitcode ("rrc", "a");
6381 if (isSameRegs && offl==MSB16) {
6382 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6384 aopPut (AOP (result), "a", MSB32);
6385 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6388 emitcode ("rrc", "a");
6389 if (isSameRegs && offl==1) {
6390 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6392 aopPut (AOP (result), "a", MSB24);
6393 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6395 emitcode ("rrc", "a");
6396 aopPut (AOP (result), "a", MSB16 - offl);
6400 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6401 emitcode ("rrc", "a");
6402 aopPut (AOP (result), "a", LSB);
6406 /*-----------------------------------------------------------------*/
6407 /* genrshFour - shift four byte by a known amount != 0 */
6408 /*-----------------------------------------------------------------*/
6410 genrshFour (operand * result, operand * left,
6411 int shCount, int sign)
6413 /* if shifting more that 3 bytes */
6418 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6420 movLeft2Result (left, MSB32, result, LSB, sign);
6421 addSign (result, MSB16, sign);
6423 else if (shCount >= 16)
6427 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6430 movLeft2Result (left, MSB24, result, LSB, 0);
6431 movLeft2Result (left, MSB32, result, MSB16, sign);
6433 addSign (result, MSB24, sign);
6435 else if (shCount >= 8)
6439 shiftRLong (left, MSB16, result, sign);
6440 else if (shCount == 0)
6442 movLeft2Result (left, MSB16, result, LSB, 0);
6443 movLeft2Result (left, MSB24, result, MSB16, 0);
6444 movLeft2Result (left, MSB32, result, MSB24, sign);
6445 addSign (result, MSB32, sign);
6449 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6450 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6451 /* the last shift is signed */
6452 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6453 addSign (result, MSB32, sign);
6457 { /* 1 <= shCount <= 7 */
6460 shiftRLong (left, LSB, result, sign);
6462 shiftRLong (result, LSB, result, sign);
6466 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6467 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6468 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6473 /*-----------------------------------------------------------------*/
6474 /* genRightShiftLiteral - right shifting by known count */
6475 /*-----------------------------------------------------------------*/
6477 genRightShiftLiteral (operand * left,
6483 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6486 freeAsmop (right, NULL, ic, TRUE);
6488 aopOp (left, ic, FALSE);
6489 aopOp (result, ic, FALSE);
6492 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6496 size = getDataSize (left);
6497 /* test the LEFT size !!! */
6499 /* I suppose that the left size >= result size */
6502 size = getDataSize (result);
6504 movLeft2Result (left, size, result, size, 0);
6507 else if (shCount >= (size * 8))
6510 /* get sign in acc.7 */
6511 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6512 addSign (result, LSB, sign);
6519 genrshOne (result, left, shCount, sign);
6523 genrshTwo (result, left, shCount, sign);
6527 genrshFour (result, left, shCount, sign);
6533 freeAsmop (left, NULL, ic, TRUE);
6534 freeAsmop (result, NULL, ic, TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genSignedRightShift - right shift of signed number */
6540 /*-----------------------------------------------------------------*/
6542 genSignedRightShift (iCode * ic)
6544 operand *right, *left, *result;
6547 symbol *tlbl, *tlbl1;
6549 /* we do it the hard way put the shift count in b
6550 and loop thru preserving the sign */
6552 right = IC_RIGHT (ic);
6553 left = IC_LEFT (ic);
6554 result = IC_RESULT (ic);
6556 aopOp (right, ic, FALSE);
6559 if (AOP_TYPE (right) == AOP_LIT)
6561 genRightShiftLiteral (left, right, result, ic, 1);
6564 /* shift count is unknown then we have to form
6565 a loop get the loop count in B : Note: we take
6566 only the lower order byte since shifting
6567 more that 32 bits make no sense anyway, ( the
6568 largest size of an object can be only 32 bits ) */
6570 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6571 emitcode ("inc", "b");
6572 freeAsmop (right, NULL, ic, TRUE);
6573 aopOp (left, ic, FALSE);
6574 aopOp (result, ic, FALSE);
6576 /* now move the left to the result if they are not the
6578 if (!sameRegs (AOP (left), AOP (result)) &&
6579 AOP_SIZE (result) > 1)
6582 size = AOP_SIZE (result);
6586 l = aopGet (AOP (left), offset, FALSE, TRUE);
6587 if (*l == '@' && IS_AOP_PREG (result))
6590 emitcode ("mov", "a,%s", l);
6591 aopPut (AOP (result), "a", offset);
6594 aopPut (AOP (result), l, offset);
6599 /* mov the highest order bit to OVR */
6600 tlbl = newiTempLabel (NULL);
6601 tlbl1 = newiTempLabel (NULL);
6603 size = AOP_SIZE (result);
6605 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6606 emitcode ("rlc", "a");
6607 emitcode ("mov", "ov,c");
6608 /* if it is only one byte then */
6611 l = aopGet (AOP (left), 0, FALSE, FALSE);
6613 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6614 emitcode ("", "%05d$:", tlbl->key + 100);
6615 emitcode ("mov", "c,ov");
6616 emitcode ("rrc", "a");
6617 emitcode ("", "%05d$:", tlbl1->key + 100);
6618 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6619 aopPut (AOP (result), "a", 0);
6623 reAdjustPreg (AOP (result));
6624 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6625 emitcode ("", "%05d$:", tlbl->key + 100);
6626 emitcode ("mov", "c,ov");
6629 l = aopGet (AOP (result), offset, FALSE, FALSE);
6631 emitcode ("rrc", "a");
6632 aopPut (AOP (result), "a", offset--);
6634 reAdjustPreg (AOP (result));
6635 emitcode ("", "%05d$:", tlbl1->key + 100);
6636 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6639 freeAsmop (left, NULL, ic, TRUE);
6640 freeAsmop (result, NULL, ic, TRUE);
6643 /*-----------------------------------------------------------------*/
6644 /* genRightShift - generate code for right shifting */
6645 /*-----------------------------------------------------------------*/
6647 genRightShift (iCode * ic)
6649 operand *right, *left, *result;
6653 symbol *tlbl, *tlbl1;
6655 /* if signed then we do it the hard way preserve the
6656 sign bit moving it inwards */
6657 retype = getSpec (operandType (IC_RESULT (ic)));
6659 if (!SPEC_USIGN (retype))
6661 genSignedRightShift (ic);
6665 /* signed & unsigned types are treated the same : i.e. the
6666 signed is NOT propagated inwards : quoting from the
6667 ANSI - standard : "for E1 >> E2, is equivalent to division
6668 by 2**E2 if unsigned or if it has a non-negative value,
6669 otherwise the result is implementation defined ", MY definition
6670 is that the sign does not get propagated */
6672 right = IC_RIGHT (ic);
6673 left = IC_LEFT (ic);
6674 result = IC_RESULT (ic);
6676 aopOp (right, ic, FALSE);
6678 /* if the shift count is known then do it
6679 as efficiently as possible */
6680 if (AOP_TYPE (right) == AOP_LIT)
6682 genRightShiftLiteral (left, right, result, ic, 0);
6686 /* shift count is unknown then we have to form
6687 a loop get the loop count in B : Note: we take
6688 only the lower order byte since shifting
6689 more that 32 bits make no sense anyway, ( the
6690 largest size of an object can be only 32 bits ) */
6692 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6693 emitcode ("inc", "b");
6694 freeAsmop (right, NULL, ic, TRUE);
6695 aopOp (left, ic, FALSE);
6696 aopOp (result, ic, FALSE);
6698 /* now move the left to the result if they are not the
6700 if (!sameRegs (AOP (left), AOP (result)) &&
6701 AOP_SIZE (result) > 1)
6704 size = AOP_SIZE (result);
6708 l = aopGet (AOP (left), offset, FALSE, TRUE);
6709 if (*l == '@' && IS_AOP_PREG (result))
6712 emitcode ("mov", "a,%s", l);
6713 aopPut (AOP (result), "a", offset);
6716 aopPut (AOP (result), l, offset);
6721 tlbl = newiTempLabel (NULL);
6722 tlbl1 = newiTempLabel (NULL);
6723 size = AOP_SIZE (result);
6726 /* if it is only one byte then */
6729 l = aopGet (AOP (left), 0, FALSE, FALSE);
6731 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6732 emitcode ("", "%05d$:", tlbl->key + 100);
6734 emitcode ("rrc", "a");
6735 emitcode ("", "%05d$:", tlbl1->key + 100);
6736 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6737 aopPut (AOP (result), "a", 0);
6741 reAdjustPreg (AOP (result));
6742 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6743 emitcode ("", "%05d$:", tlbl->key + 100);
6747 l = aopGet (AOP (result), offset, FALSE, FALSE);
6749 emitcode ("rrc", "a");
6750 aopPut (AOP (result), "a", offset--);
6752 reAdjustPreg (AOP (result));
6754 emitcode ("", "%05d$:", tlbl1->key + 100);
6755 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6758 freeAsmop (left, NULL, ic, TRUE);
6759 freeAsmop (result, NULL, ic, TRUE);
6762 /*-----------------------------------------------------------------*/
6763 /* genUnpackBits - generates code for unpacking bits */
6764 /*-----------------------------------------------------------------*/
6766 genUnpackBits (operand * result, char *rname, int ptype)
6774 etype = getSpec (operandType (result));
6775 rsize = getSize (operandType (result));
6776 /* read the first byte */
6782 emitcode ("mov", "a,@%s", rname);
6786 emitcode ("movx", "a,@%s", rname);
6790 emitcode ("movx", "a,@dptr");
6794 emitcode ("clr", "a");
6795 emitcode ("movc", "a,%s", "@a+dptr");
6799 emitcode ("lcall", "__gptrget");
6803 rlen = SPEC_BLEN (etype);
6805 /* if we have bitdisplacement then it fits */
6806 /* into this byte completely or if length is */
6807 /* less than a byte */
6808 if ((shCnt = SPEC_BSTR (etype)) ||
6809 (SPEC_BLEN (etype) <= 8))
6812 /* shift right acc */
6815 emitcode ("anl", "a,#0x%02x",
6816 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6817 aopPut (AOP (result), "a", offset++);
6821 /* bit field did not fit in a byte */
6822 aopPut (AOP (result), "a", offset++);
6831 emitcode ("inc", "%s", rname);
6832 emitcode ("mov", "a,@%s", rname);
6836 emitcode ("inc", "%s", rname);
6837 emitcode ("movx", "a,@%s", rname);
6841 emitcode ("inc", "dptr");
6842 emitcode ("movx", "a,@dptr");
6846 emitcode ("clr", "a");
6847 emitcode ("inc", "dptr");
6848 emitcode ("movc", "a", "@a+dptr");
6852 emitcode ("inc", "dptr");
6853 emitcode ("lcall", "__gptrget");
6858 /* if we are done */
6862 aopPut (AOP (result), "a", offset++);
6868 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6870 aopPut (AOP (result), "a", offset++);
6878 aopPut (AOP (result), zero, offset++);
6884 /*-----------------------------------------------------------------*/
6885 /* genDataPointerGet - generates code when ptr offset is known */
6886 /*-----------------------------------------------------------------*/
6888 genDataPointerGet (operand * left,
6894 int size, offset = 0;
6895 aopOp (result, ic, TRUE);
6897 /* get the string representation of the name */
6898 l = aopGet (AOP (left), 0, FALSE, TRUE);
6899 size = AOP_SIZE (result);
6903 sprintf (buffer, "(%s + %d)", l + 1, offset);
6905 sprintf (buffer, "%s", l + 1);
6906 aopPut (AOP (result), buffer, offset++);
6909 freeAsmop (left, NULL, ic, TRUE);
6910 freeAsmop (result, NULL, ic, TRUE);
6913 /*-----------------------------------------------------------------*/
6914 /* genNearPointerGet - emitcode for near pointer fetch */
6915 /*-----------------------------------------------------------------*/
6917 genNearPointerGet (operand * left,
6925 sym_link *rtype, *retype;
6926 sym_link *ltype = operandType (left);
6929 rtype = operandType (result);
6930 retype = getSpec (rtype);
6932 aopOp (left, ic, FALSE);
6934 /* if left is rematerialisable and
6935 result is not bit variable type and
6936 the left is pointer to data space i.e
6937 lower 128 bytes of space */
6938 if (AOP_TYPE (left) == AOP_IMMD &&
6939 !IS_BITVAR (retype) &&
6940 DCL_TYPE (ltype) == POINTER)
6942 genDataPointerGet (left, result, ic);
6946 /* if the value is already in a pointer register
6947 then don't need anything more */
6948 if (!AOP_INPREG (AOP (left)))
6950 /* otherwise get a free pointer register */
6952 preg = getFreePtr (ic, &aop, FALSE);
6953 emitcode ("mov", "%s,%s",
6955 aopGet (AOP (left), 0, FALSE, TRUE));
6959 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6961 aopOp (result, ic, FALSE);
6963 /* if bitfield then unpack the bits */
6964 if (IS_BITVAR (retype))
6965 genUnpackBits (result, rname, POINTER);
6968 /* we have can just get the values */
6969 int size = AOP_SIZE (result);
6974 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6977 emitcode ("mov", "a,@%s", rname);
6978 aopPut (AOP (result), "a", offset);
6982 sprintf (buffer, "@%s", rname);
6983 aopPut (AOP (result), buffer, offset);
6987 emitcode ("inc", "%s", rname);
6991 /* now some housekeeping stuff */
6992 if (aop) /* we had to allocate for this iCode */
6994 if (pi) { /* post increment present */
6995 aopPut(AOP ( left ),rname,0);
6997 freeAsmop (NULL, aop, ic, TRUE);
7001 /* we did not allocate which means left
7002 already in a pointer register, then
7003 if size > 0 && this could be used again
7004 we have to point it back to where it
7006 if ((AOP_SIZE (result) > 1 &&
7007 !OP_SYMBOL (left)->remat &&
7008 (OP_SYMBOL (left)->liveTo > ic->seq ||
7012 int size = AOP_SIZE (result) - 1;
7014 emitcode ("dec", "%s", rname);
7019 freeAsmop (left, NULL, ic, TRUE);
7020 freeAsmop (result, NULL, ic, TRUE);
7021 if (pi) pi->generated = 1;
7024 /*-----------------------------------------------------------------*/
7025 /* genPagedPointerGet - emitcode for paged pointer fetch */
7026 /*-----------------------------------------------------------------*/
7028 genPagedPointerGet (operand * left,
7036 sym_link *rtype, *retype;
7038 rtype = operandType (result);
7039 retype = getSpec (rtype);
7041 aopOp (left, ic, FALSE);
7043 /* if the value is already in a pointer register
7044 then don't need anything more */
7045 if (!AOP_INPREG (AOP (left)))
7047 /* otherwise get a free pointer register */
7049 preg = getFreePtr (ic, &aop, FALSE);
7050 emitcode ("mov", "%s,%s",
7052 aopGet (AOP (left), 0, FALSE, TRUE));
7056 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7058 aopOp (result, ic, FALSE);
7060 /* if bitfield then unpack the bits */
7061 if (IS_BITVAR (retype))
7062 genUnpackBits (result, rname, PPOINTER);
7065 /* we have can just get the values */
7066 int size = AOP_SIZE (result);
7072 emitcode ("movx", "a,@%s", rname);
7073 aopPut (AOP (result), "a", offset);
7078 emitcode ("inc", "%s", rname);
7082 /* now some housekeeping stuff */
7083 if (aop) /* we had to allocate for this iCode */
7085 if (pi) aopPut ( AOP (left), rname, 0);
7086 freeAsmop (NULL, aop, ic, TRUE);
7090 /* we did not allocate which means left
7091 already in a pointer register, then
7092 if size > 0 && this could be used again
7093 we have to point it back to where it
7095 if ((AOP_SIZE (result) > 1 &&
7096 !OP_SYMBOL (left)->remat &&
7097 (OP_SYMBOL (left)->liveTo > ic->seq ||
7101 int size = AOP_SIZE (result) - 1;
7103 emitcode ("dec", "%s", rname);
7108 freeAsmop (left, NULL, ic, TRUE);
7109 freeAsmop (result, NULL, ic, TRUE);
7110 if (pi) pi->generated = 1;
7114 /*-----------------------------------------------------------------*/
7115 /* genFarPointerGet - gget value from far space */
7116 /*-----------------------------------------------------------------*/
7118 genFarPointerGet (operand * left,
7119 operand * result, iCode * ic, iCode * pi)
7122 sym_link *retype = getSpec (operandType (result));
7124 aopOp (left, ic, FALSE);
7126 /* if the operand is already in dptr
7127 then we do nothing else we move the value to dptr */
7128 if (AOP_TYPE (left) != AOP_STR)
7130 /* if this is remateriazable */
7131 if (AOP_TYPE (left) == AOP_IMMD)
7132 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7134 { /* we need to get it byte by byte */
7135 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7136 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7139 /* so dptr know contains the address */
7140 aopOp (result, ic, FALSE);
7142 /* if bit then unpack */
7143 if (IS_BITVAR (retype))
7144 genUnpackBits (result, "dptr", FPOINTER);
7147 size = AOP_SIZE (result);
7152 emitcode ("movx", "a,@dptr");
7153 aopPut (AOP (result), "a", offset++);
7155 emitcode ("inc", "dptr");
7159 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7160 aopPut ( AOP (left), "dpl", 0);
7161 aopPut ( AOP (left), "dph", 1);
7164 freeAsmop (left, NULL, ic, TRUE);
7165 freeAsmop (result, NULL, ic, TRUE);
7168 /*-----------------------------------------------------------------*/
7169 /* genCodePointerGet - gget value from code space */
7170 /*-----------------------------------------------------------------*/
7172 genCodePointerGet (operand * left,
7173 operand * result, iCode * ic, iCode *pi)
7176 sym_link *retype = getSpec (operandType (result));
7178 aopOp (left, ic, FALSE);
7180 /* if the operand is already in dptr
7181 then we do nothing else we move the value to dptr */
7182 if (AOP_TYPE (left) != AOP_STR)
7184 /* if this is remateriazable */
7185 if (AOP_TYPE (left) == AOP_IMMD)
7186 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7188 { /* we need to get it byte by byte */
7189 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7190 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7193 /* so dptr know contains the address */
7194 aopOp (result, ic, FALSE);
7196 /* if bit then unpack */
7197 if (IS_BITVAR (retype))
7198 genUnpackBits (result, "dptr", CPOINTER);
7201 size = AOP_SIZE (result);
7206 emitcode ("clr", "a");
7207 emitcode ("movc", "a,@a+dptr");
7208 aopPut (AOP (result), "a", offset++);
7210 emitcode ("inc", "dptr");
7214 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7215 aopPut ( AOP (left), "dpl", 0);
7216 aopPut ( AOP (left), "dph", 1);
7219 freeAsmop (left, NULL, ic, TRUE);
7220 freeAsmop (result, NULL, ic, TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genGenPointerGet - gget value from generic pointer space */
7225 /*-----------------------------------------------------------------*/
7227 genGenPointerGet (operand * left,
7228 operand * result, iCode * ic, iCode *pi)
7231 sym_link *retype = getSpec (operandType (result));
7233 aopOp (left, ic, FALSE);
7235 /* if the operand is already in dptr
7236 then we do nothing else we move the value to dptr */
7237 if (AOP_TYPE (left) != AOP_STR)
7239 /* if this is remateriazable */
7240 if (AOP_TYPE (left) == AOP_IMMD)
7242 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7243 emitcode ("mov", "b,#%d", pointerCode (retype));
7246 { /* we need to get it byte by byte */
7247 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7248 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7249 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7252 /* so dptr know contains the address */
7253 aopOp (result, ic, FALSE);
7255 /* if bit then unpack */
7256 if (IS_BITVAR (retype))
7257 genUnpackBits (result, "dptr", GPOINTER);
7260 size = AOP_SIZE (result);
7265 emitcode ("lcall", "__gptrget");
7266 aopPut (AOP (result), "a", offset++);
7268 emitcode ("inc", "dptr");
7272 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7273 aopPut ( AOP (left), "dpl", 0);
7274 aopPut ( AOP (left), "dph", 1);
7277 freeAsmop (left, NULL, ic, TRUE);
7278 freeAsmop (result, NULL, ic, TRUE);
7281 /*-----------------------------------------------------------------*/
7282 /* genPointerGet - generate code for pointer get */
7283 /*-----------------------------------------------------------------*/
7285 genPointerGet (iCode * ic, iCode *pi)
7287 operand *left, *result;
7288 sym_link *type, *etype;
7291 left = IC_LEFT (ic);
7292 result = IC_RESULT (ic);
7294 /* depending on the type of pointer we need to
7295 move it to the correct pointer register */
7296 type = operandType (left);
7297 etype = getSpec (type);
7298 /* if left is of type of pointer then it is simple */
7299 if (IS_PTR (type) && !IS_FUNC (type->next))
7300 p_type = DCL_TYPE (type);
7303 /* we have to go by the storage class */
7304 p_type = PTR_TYPE (SPEC_OCLS (etype));
7307 /* now that we have the pointer type we assign
7308 the pointer values */
7314 genNearPointerGet (left, result, ic, pi);
7318 genPagedPointerGet (left, result, ic, pi);
7322 genFarPointerGet (left, result, ic, pi);
7326 genCodePointerGet (left, result, ic, pi);
7330 genGenPointerGet (left, result, ic, pi);
7336 /*-----------------------------------------------------------------*/
7337 /* genPackBits - generates code for packed bit storage */
7338 /*-----------------------------------------------------------------*/
7340 genPackBits (sym_link * etype,
7342 char *rname, int p_type)
7350 blen = SPEC_BLEN (etype);
7351 bstr = SPEC_BSTR (etype);
7353 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7356 /* if the bit lenth is less than or */
7357 /* it exactly fits a byte then */
7358 if (SPEC_BLEN (etype) <= 8)
7360 shCount = SPEC_BSTR (etype);
7362 /* shift left acc */
7365 if (SPEC_BLEN (etype) < 8)
7366 { /* if smaller than a byte */
7372 emitcode ("mov", "b,a");
7373 emitcode ("mov", "a,@%s", rname);
7377 emitcode ("mov", "b,a");
7378 emitcode ("movx", "a,@dptr");
7382 emitcode ("push", "b");
7383 emitcode ("push", "acc");
7384 emitcode ("lcall", "__gptrget");
7385 emitcode ("pop", "b");
7389 emitcode ("anl", "a,#0x%02x", (unsigned char)
7390 ((unsigned char) (0xFF << (blen + bstr)) |
7391 (unsigned char) (0xFF >> (8 - bstr))));
7392 emitcode ("orl", "a,b");
7393 if (p_type == GPOINTER)
7394 emitcode ("pop", "b");
7401 emitcode ("mov", "@%s,a", rname);
7405 emitcode ("movx", "@dptr,a");
7409 emitcode ("lcall", "__gptrput");
7414 if (SPEC_BLEN (etype) <= 8)
7417 emitcode ("inc", "%s", rname);
7418 rLen = SPEC_BLEN (etype);
7420 /* now generate for lengths greater than one byte */
7424 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7436 emitcode ("mov", "@%s,a", rname);
7439 emitcode ("mov", "@%s,%s", rname, l);
7444 emitcode ("movx", "@dptr,a");
7449 emitcode ("lcall", "__gptrput");
7452 emitcode ("inc", "%s", rname);
7457 /* last last was not complete */
7460 /* save the byte & read byte */
7464 emitcode ("mov", "b,a");
7465 emitcode ("mov", "a,@%s", rname);
7469 emitcode ("mov", "b,a");
7470 emitcode ("movx", "a,@dptr");
7474 emitcode ("push", "b");
7475 emitcode ("push", "acc");
7476 emitcode ("lcall", "__gptrget");
7477 emitcode ("pop", "b");
7481 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7482 emitcode ("orl", "a,b");
7485 if (p_type == GPOINTER)
7486 emitcode ("pop", "b");
7492 emitcode ("mov", "@%s,a", rname);
7496 emitcode ("movx", "@dptr,a");
7500 emitcode ("lcall", "__gptrput");
7504 /*-----------------------------------------------------------------*/
7505 /* genDataPointerSet - remat pointer to data space */
7506 /*-----------------------------------------------------------------*/
7508 genDataPointerSet (operand * right,
7512 int size, offset = 0;
7513 char *l, buffer[256];
7515 aopOp (right, ic, FALSE);
7517 l = aopGet (AOP (result), 0, FALSE, TRUE);
7518 size = AOP_SIZE (right);
7522 sprintf (buffer, "(%s + %d)", l + 1, offset);
7524 sprintf (buffer, "%s", l + 1);
7525 emitcode ("mov", "%s,%s", buffer,
7526 aopGet (AOP (right), offset++, FALSE, FALSE));
7529 freeAsmop (right, NULL, ic, TRUE);
7530 freeAsmop (result, NULL, ic, TRUE);
7533 /*-----------------------------------------------------------------*/
7534 /* genNearPointerSet - emitcode for near pointer put */
7535 /*-----------------------------------------------------------------*/
7537 genNearPointerSet (operand * right,
7545 sym_link *retype, *letype;
7546 sym_link *ptype = operandType (result);
7548 retype = getSpec (operandType (right));
7549 letype = getSpec (ptype);
7550 aopOp (result, ic, FALSE);
7552 /* if the result is rematerializable &
7553 in data space & not a bit variable */
7554 if (AOP_TYPE (result) == AOP_IMMD &&
7555 DCL_TYPE (ptype) == POINTER &&
7556 !IS_BITVAR (retype) &&
7557 !IS_BITVAR (letype))
7559 genDataPointerSet (right, result, ic);
7563 /* if the value is already in a pointer register
7564 then don't need anything more */
7565 if (!AOP_INPREG (AOP (result)))
7567 /* otherwise get a free pointer register */
7569 preg = getFreePtr (ic, &aop, FALSE);
7570 emitcode ("mov", "%s,%s",
7572 aopGet (AOP (result), 0, FALSE, TRUE));
7576 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7578 aopOp (right, ic, FALSE);
7580 /* if bitfield then unpack the bits */
7581 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7582 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7585 /* we have can just get the values */
7586 int size = AOP_SIZE (right);
7591 l = aopGet (AOP (right), offset, FALSE, TRUE);
7595 emitcode ("mov", "@%s,a", rname);
7598 emitcode ("mov", "@%s,%s", rname, l);
7600 emitcode ("inc", "%s", rname);
7605 /* now some housekeeping stuff */
7606 if (aop) /* we had to allocate for this iCode */
7608 if (pi) aopPut (AOP (result),rname,0);
7609 freeAsmop (NULL, aop, ic, TRUE);
7613 /* we did not allocate which means left
7614 already in a pointer register, then
7615 if size > 0 && this could be used again
7616 we have to point it back to where it
7618 if ((AOP_SIZE (right) > 1 &&
7619 !OP_SYMBOL (result)->remat &&
7620 (OP_SYMBOL (result)->liveTo > ic->seq ||
7624 int size = AOP_SIZE (right) - 1;
7626 emitcode ("dec", "%s", rname);
7631 if (pi) pi->generated = 1;
7632 freeAsmop (result, NULL, ic, TRUE);
7633 freeAsmop (right, NULL, ic, TRUE);
7636 /*-----------------------------------------------------------------*/
7637 /* genPagedPointerSet - emitcode for Paged pointer put */
7638 /*-----------------------------------------------------------------*/
7640 genPagedPointerSet (operand * right,
7648 sym_link *retype, *letype;
7650 retype = getSpec (operandType (right));
7651 letype = getSpec (operandType (result));
7653 aopOp (result, ic, FALSE);
7655 /* if the value is already in a pointer register
7656 then don't need anything more */
7657 if (!AOP_INPREG (AOP (result)))
7659 /* otherwise get a free pointer register */
7661 preg = getFreePtr (ic, &aop, FALSE);
7662 emitcode ("mov", "%s,%s",
7664 aopGet (AOP (result), 0, FALSE, TRUE));
7668 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7670 aopOp (right, ic, FALSE);
7672 /* if bitfield then unpack the bits */
7673 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7674 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7677 /* we have can just get the values */
7678 int size = AOP_SIZE (right);
7683 l = aopGet (AOP (right), offset, FALSE, TRUE);
7686 emitcode ("movx", "@%s,a", rname);
7689 emitcode ("inc", "%s", rname);
7695 /* now some housekeeping stuff */
7696 if (aop) /* we had to allocate for this iCode */
7698 if (pi) aopPut (AOP (result),rname,0);
7699 freeAsmop (NULL, aop, ic, TRUE);
7703 /* we did not allocate which means left
7704 already in a pointer register, then
7705 if size > 0 && this could be used again
7706 we have to point it back to where it
7708 if (AOP_SIZE (right) > 1 &&
7709 !OP_SYMBOL (result)->remat &&
7710 (OP_SYMBOL (result)->liveTo > ic->seq ||
7713 int size = AOP_SIZE (right) - 1;
7715 emitcode ("dec", "%s", rname);
7720 if (pi) pi->generated = 1;
7721 freeAsmop (result, NULL, ic, TRUE);
7722 freeAsmop (right, NULL, ic, TRUE);
7727 /*-----------------------------------------------------------------*/
7728 /* genFarPointerSet - set value from far space */
7729 /*-----------------------------------------------------------------*/
7731 genFarPointerSet (operand * right,
7732 operand * result, iCode * ic, iCode * pi)
7735 sym_link *retype = getSpec (operandType (right));
7736 sym_link *letype = getSpec (operandType (result));
7737 aopOp (result, ic, FALSE);
7739 /* if the operand is already in dptr
7740 then we do nothing else we move the value to dptr */
7741 if (AOP_TYPE (result) != AOP_STR)
7743 /* if this is remateriazable */
7744 if (AOP_TYPE (result) == AOP_IMMD)
7745 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7747 { /* we need to get it byte by byte */
7748 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7749 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7752 /* so dptr know contains the address */
7753 aopOp (right, ic, FALSE);
7755 /* if bit then unpack */
7756 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7757 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7760 size = AOP_SIZE (right);
7765 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7767 emitcode ("movx", "@dptr,a");
7769 emitcode ("inc", "dptr");
7772 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7773 aopPut (AOP(result),"dpl",0);
7774 aopPut (AOP(result),"dph",1);
7777 freeAsmop (result, NULL, ic, TRUE);
7778 freeAsmop (right, NULL, ic, TRUE);
7781 /*-----------------------------------------------------------------*/
7782 /* genGenPointerSet - set value from generic pointer space */
7783 /*-----------------------------------------------------------------*/
7785 genGenPointerSet (operand * right,
7786 operand * result, iCode * ic, iCode * pi)
7789 sym_link *retype = getSpec (operandType (right));
7790 sym_link *letype = getSpec (operandType (result));
7792 aopOp (result, ic, FALSE);
7794 /* if the operand is already in dptr
7795 then we do nothing else we move the value to dptr */
7796 if (AOP_TYPE (result) != AOP_STR)
7798 /* if this is remateriazable */
7799 if (AOP_TYPE (result) == AOP_IMMD)
7801 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7802 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7805 { /* we need to get it byte by byte */
7806 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7807 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7808 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7811 /* so dptr know contains the address */
7812 aopOp (right, ic, FALSE);
7814 /* if bit then unpack */
7815 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7816 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7819 size = AOP_SIZE (right);
7824 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7826 emitcode ("lcall", "__gptrput");
7828 emitcode ("inc", "dptr");
7832 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7833 aopPut (AOP(result),"dpl",0);
7834 aopPut (AOP(result),"dph",1);
7837 freeAsmop (result, NULL, ic, TRUE);
7838 freeAsmop (right, NULL, ic, TRUE);
7841 /*-----------------------------------------------------------------*/
7842 /* genPointerSet - stores the value into a pointer location */
7843 /*-----------------------------------------------------------------*/
7845 genPointerSet (iCode * ic, iCode *pi)
7847 operand *right, *result;
7848 sym_link *type, *etype;
7851 right = IC_RIGHT (ic);
7852 result = IC_RESULT (ic);
7854 /* depending on the type of pointer we need to
7855 move it to the correct pointer register */
7856 type = operandType (result);
7857 etype = getSpec (type);
7858 /* if left is of type of pointer then it is simple */
7859 if (IS_PTR (type) && !IS_FUNC (type->next))
7861 p_type = DCL_TYPE (type);
7865 /* we have to go by the storage class */
7866 p_type = PTR_TYPE (SPEC_OCLS (etype));
7869 /* now that we have the pointer type we assign
7870 the pointer values */
7876 genNearPointerSet (right, result, ic, pi);
7880 genPagedPointerSet (right, result, ic, pi);
7884 genFarPointerSet (right, result, ic, pi);
7888 genGenPointerSet (right, result, ic, pi);
7894 /*-----------------------------------------------------------------*/
7895 /* genIfx - generate code for Ifx statement */
7896 /*-----------------------------------------------------------------*/
7898 genIfx (iCode * ic, iCode * popIc)
7900 operand *cond = IC_COND (ic);
7903 aopOp (cond, ic, FALSE);
7905 /* get the value into acc */
7906 if (AOP_TYPE (cond) != AOP_CRY)
7910 /* the result is now in the accumulator */
7911 freeAsmop (cond, NULL, ic, TRUE);
7913 /* if there was something to be popped then do it */
7917 /* if the condition is a bit variable */
7918 if (isbit && IS_ITEMP (cond) &&
7920 genIfxJump (ic, SPIL_LOC (cond)->rname);
7921 else if (isbit && !IS_ITEMP (cond))
7922 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7924 genIfxJump (ic, "a");
7929 /*-----------------------------------------------------------------*/
7930 /* genAddrOf - generates code for address of */
7931 /*-----------------------------------------------------------------*/
7933 genAddrOf (iCode * ic)
7935 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7938 aopOp (IC_RESULT (ic), ic, FALSE);
7940 /* if the operand is on the stack then we
7941 need to get the stack offset of this
7945 /* if it has an offset then we need to compute
7949 emitcode ("mov", "a,_bp");
7950 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7951 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7955 /* we can just move _bp */
7956 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7958 /* fill the result with zero */
7959 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7964 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7970 /* object not on stack then we need the name */
7971 size = AOP_SIZE (IC_RESULT (ic));
7976 char s[SDCC_NAME_MAX];
7978 sprintf (s, "#(%s >> %d)",
7982 sprintf (s, "#%s", sym->rname);
7983 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genFarFarAssign - assignment when both are in far space */
7993 /*-----------------------------------------------------------------*/
7995 genFarFarAssign (operand * result, operand * right, iCode * ic)
7997 int size = AOP_SIZE (right);
8000 /* first push the right side on to the stack */
8003 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8005 emitcode ("push", "acc");
8008 freeAsmop (right, NULL, ic, FALSE);
8009 /* now assign DPTR to result */
8010 aopOp (result, ic, FALSE);
8011 size = AOP_SIZE (result);
8014 emitcode ("pop", "acc");
8015 aopPut (AOP (result), "a", --offset);
8017 freeAsmop (result, NULL, ic, FALSE);
8021 /*-----------------------------------------------------------------*/
8022 /* genAssign - generate code for assignment */
8023 /*-----------------------------------------------------------------*/
8025 genAssign (iCode * ic)
8027 operand *result, *right;
8029 unsigned long lit = 0L;
8031 D(emitcode(";","genAssign"));
8033 result = IC_RESULT (ic);
8034 right = IC_RIGHT (ic);
8036 /* if they are the same */
8037 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8040 aopOp (right, ic, FALSE);
8042 /* special case both in far space */
8043 if (AOP_TYPE (right) == AOP_DPTR &&
8044 IS_TRUE_SYMOP (result) &&
8045 isOperandInFarSpace (result))
8048 genFarFarAssign (result, right, ic);
8052 aopOp (result, ic, TRUE);
8054 /* if they are the same registers */
8055 if (sameRegs (AOP (right), AOP (result)))
8058 /* if the result is a bit */
8059 if (AOP_TYPE (result) == AOP_CRY)
8062 /* if the right size is a literal then
8063 we know what the value is */
8064 if (AOP_TYPE (right) == AOP_LIT)
8066 if (((int) operandLitValue (right)))
8067 aopPut (AOP (result), one, 0);
8069 aopPut (AOP (result), zero, 0);
8073 /* the right is also a bit variable */
8074 if (AOP_TYPE (right) == AOP_CRY)
8076 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8077 aopPut (AOP (result), "c", 0);
8083 aopPut (AOP (result), "a", 0);
8087 /* bit variables done */
8089 size = AOP_SIZE (result);
8091 if (AOP_TYPE (right) == AOP_LIT)
8092 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8094 (AOP_TYPE (result) != AOP_REG) &&
8095 (AOP_TYPE (right) == AOP_LIT) &&
8096 !IS_FLOAT (operandType (right)) &&
8099 emitcode ("clr", "a");
8102 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8103 aopPut (AOP (result), "a", size);
8105 aopPut (AOP (result),
8106 aopGet (AOP (right), size, FALSE, FALSE),
8114 aopPut (AOP (result),
8115 aopGet (AOP (right), offset, FALSE, FALSE),
8122 freeAsmop (right, NULL, ic, TRUE);
8123 freeAsmop (result, NULL, ic, TRUE);
8126 /*-----------------------------------------------------------------*/
8127 /* genJumpTab - genrates code for jump table */
8128 /*-----------------------------------------------------------------*/
8130 genJumpTab (iCode * ic)
8135 aopOp (IC_JTCOND (ic), ic, FALSE);
8136 /* get the condition into accumulator */
8137 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8139 /* multiply by three */
8140 emitcode ("add", "a,acc");
8141 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8142 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8144 jtab = newiTempLabel (NULL);
8145 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8146 emitcode ("jmp", "@a+dptr");
8147 emitcode ("", "%05d$:", jtab->key + 100);
8148 /* now generate the jump labels */
8149 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8150 jtab = setNextItem (IC_JTLABELS (ic)))
8151 emitcode ("ljmp", "%05d$", jtab->key + 100);
8155 /*-----------------------------------------------------------------*/
8156 /* genCast - gen code for casting */
8157 /*-----------------------------------------------------------------*/
8159 genCast (iCode * ic)
8161 operand *result = IC_RESULT (ic);
8162 sym_link *ctype = operandType (IC_LEFT (ic));
8163 sym_link *rtype = operandType (IC_RIGHT (ic));
8164 operand *right = IC_RIGHT (ic);
8167 D(emitcode(";", "genCast"));
8169 /* if they are equivalent then do nothing */
8170 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8173 aopOp (right, ic, FALSE);
8174 aopOp (result, ic, FALSE);
8176 /* if the result is a bit */
8177 if (AOP_TYPE (result) == AOP_CRY)
8179 /* if the right size is a literal then
8180 we know what the value is */
8181 if (AOP_TYPE (right) == AOP_LIT)
8183 if (((int) operandLitValue (right)))
8184 aopPut (AOP (result), one, 0);
8186 aopPut (AOP (result), zero, 0);
8191 /* the right is also a bit variable */
8192 if (AOP_TYPE (right) == AOP_CRY)
8194 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8195 aopPut (AOP (result), "c", 0);
8201 aopPut (AOP (result), "a", 0);
8205 /* if they are the same size : or less */
8206 if (AOP_SIZE (result) <= AOP_SIZE (right))
8209 /* if they are in the same place */
8210 if (sameRegs (AOP (right), AOP (result)))
8213 /* if they in different places then copy */
8214 size = AOP_SIZE (result);
8218 aopPut (AOP (result),
8219 aopGet (AOP (right), offset, FALSE, FALSE),
8227 /* if the result is of type pointer */
8232 sym_link *type = operandType (right);
8233 sym_link *etype = getSpec (type);
8235 /* pointer to generic pointer */
8236 if (IS_GENPTR (ctype))
8241 p_type = DCL_TYPE (type);
8244 if (SPEC_SCLS(etype)==S_REGISTER) {
8245 // let's assume it is a generic pointer
8248 /* we have to go by the storage class */
8249 p_type = PTR_TYPE (SPEC_OCLS (etype));
8253 /* the first two bytes are known */
8254 size = GPTRSIZE - 1;
8258 aopPut (AOP (result),
8259 aopGet (AOP (right), offset, FALSE, FALSE),
8263 /* the last byte depending on type */
8279 case PPOINTER: // what the fck is this?
8284 /* this should never happen */
8285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8286 "got unknown pointer type");
8289 aopPut (AOP (result), l, GPTRSIZE - 1);
8293 /* just copy the pointers */
8294 size = AOP_SIZE (result);
8298 aopPut (AOP (result),
8299 aopGet (AOP (right), offset, FALSE, FALSE),
8306 /* so we now know that the size of destination is greater
8307 than the size of the source */
8308 /* we move to result for the size of source */
8309 size = AOP_SIZE (right);
8313 aopPut (AOP (result),
8314 aopGet (AOP (right), offset, FALSE, FALSE),
8319 /* now depending on the sign of the source && destination */
8320 size = AOP_SIZE (result) - AOP_SIZE (right);
8321 /* if unsigned or not an integral type */
8322 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8325 aopPut (AOP (result), zero, offset++);
8329 /* we need to extend the sign :{ */
8330 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8333 emitcode ("rlc", "a");
8334 emitcode ("subb", "a,acc");
8336 aopPut (AOP (result), "a", offset++);
8339 /* we are done hurray !!!! */
8342 freeAsmop (right, NULL, ic, TRUE);
8343 freeAsmop (result, NULL, ic, TRUE);
8347 /*-----------------------------------------------------------------*/
8348 /* genDjnz - generate decrement & jump if not zero instrucion */
8349 /*-----------------------------------------------------------------*/
8351 genDjnz (iCode * ic, iCode * ifx)
8357 /* if the if condition has a false label
8358 then we cannot save */
8362 /* if the minus is not of the form
8364 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8365 !IS_OP_LITERAL (IC_RIGHT (ic)))
8368 if (operandLitValue (IC_RIGHT (ic)) != 1)
8371 /* if the size of this greater than one then no
8373 if (getSize (operandType (IC_RESULT (ic))) > 1)
8376 /* otherwise we can save BIG */
8377 lbl = newiTempLabel (NULL);
8378 lbl1 = newiTempLabel (NULL);
8380 aopOp (IC_RESULT (ic), ic, FALSE);
8382 if (AOP_NEEDSACC(IC_RESULT(ic)))
8384 /* If the result is accessed indirectly via
8385 * the accumulator, we must explicitly write
8386 * it back after the decrement.
8388 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8390 if (strcmp(rByte, "a"))
8392 /* Something is hopelessly wrong */
8393 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8394 __FILE__, __LINE__);
8395 /* We can just give up; the generated code will be inefficient,
8398 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8401 emitcode ("dec", "%s", rByte);
8402 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8403 emitcode ("jnz", "%05d$", lbl->key + 100);
8405 else if (IS_AOP_PREG (IC_RESULT (ic)))
8407 emitcode ("dec", "%s",
8408 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8409 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8410 emitcode ("jnz", "%05d$", lbl->key + 100);
8414 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8417 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8418 emitcode ("", "%05d$:", lbl->key + 100);
8419 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8420 emitcode ("", "%05d$:", lbl1->key + 100);
8422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8427 /*-----------------------------------------------------------------*/
8428 /* genReceive - generate code for a receive iCode */
8429 /*-----------------------------------------------------------------*/
8431 genReceive (iCode * ic)
8433 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8434 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8435 IS_TRUE_SYMOP (IC_RESULT (ic))))
8438 int size = getSize (operandType (IC_RESULT (ic)));
8439 int offset = fReturnSizeMCS51 - size;
8442 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8443 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8446 aopOp (IC_RESULT (ic), ic, FALSE);
8447 size = AOP_SIZE (IC_RESULT (ic));
8451 emitcode ("pop", "acc");
8452 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8459 aopOp (IC_RESULT (ic), ic, FALSE);
8461 assignResultValue (IC_RESULT (ic));
8464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8467 /*-----------------------------------------------------------------*/
8468 /* gen51Code - generate code for 8051 based controllers */
8469 /*-----------------------------------------------------------------*/
8471 gen51Code (iCode * lic)
8476 lineHead = lineCurr = NULL;
8478 /* print the allocation information */
8480 printAllocInfo (currFunc, codeOutFile);
8481 /* if debug information required */
8482 /* if (options.debug && currFunc) { */
8483 if (options.debug && currFunc)
8485 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8487 if (IS_STATIC (currFunc->etype))
8488 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8490 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8493 /* stack pointer name */
8494 if (options.useXstack)
8500 for (ic = lic; ic; ic = ic->next)
8503 if (cln != ic->lineno)
8508 emitcode ("", "C$%s$%d$%d$%d ==.",
8509 FileBaseName (ic->filename), ic->lineno,
8510 ic->level, ic->block);
8513 emitcode (";", "%s %d", ic->filename, ic->lineno);
8516 /* if the result is marked as
8517 spilt and rematerializable or code for
8518 this has already been generated then
8520 if (resultRemat (ic) || ic->generated)
8523 /* depending on the operation */
8543 /* IPOP happens only when trying to restore a
8544 spilt live range, if there is an ifx statement
8545 following this pop then the if statement might
8546 be using some of the registers being popped which
8547 would destory the contents of the register so
8548 we need to check for this condition and handle it */
8550 ic->next->op == IFX &&
8551 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8552 genIfx (ic->next, ic);
8570 genEndFunction (ic);
8590 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8607 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8611 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8618 /* note these two are xlated by algebraic equivalence
8619 during parsing SDCC.y */
8620 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8621 "got '>=' or '<=' shouldn't have come here");
8625 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8637 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8641 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8645 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8672 case GET_VALUE_AT_ADDRESS:
8673 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8677 if (POINTER_SET (ic))
8678 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8704 addSet (&_G.sendSet, ic);
8713 /* now we are ready to call the
8714 peep hole optimizer */
8715 if (!options.nopeep)
8716 peepHole (&lineHead);
8718 /* now do the actual printing */
8719 printLine (lineHead, codeOutFile);