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 emitcode ("add", "a,#0x%02x",
3256 (unsigned int) (lit & 0x0FFL));
3258 emitcode ("addc", "a,#0x%02x",
3259 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3261 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3264 adjustArithmeticResult (ic);
3267 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3268 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3273 /*-----------------------------------------------------------------*/
3274 /* genMultbits :- multiplication of bits */
3275 /*-----------------------------------------------------------------*/
3277 genMultbits (operand * left,
3281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3282 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3287 /*-----------------------------------------------------------------*/
3288 /* genMultOneByte : 8*8=8/16 bit multiplication */
3289 /*-----------------------------------------------------------------*/
3291 genMultOneByte (operand * left,
3295 sym_link *opetype = operandType (result);
3297 int size=AOP_SIZE(result);
3299 if (size<1 || size>2) {
3300 // this should never happen
3301 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3302 AOP_SIZE(result), __FILE__, lineno);
3306 /* (if two literals: the value is computed before) */
3307 /* if one literal, literal on the right */
3308 if (AOP_TYPE (left) == AOP_LIT)
3313 //emitcode (";", "swapped left and right");
3316 if (SPEC_USIGN(opetype)
3317 // ignore the sign of left and right, what else can we do?
3318 || (SPEC_USIGN(operandType(left)) &&
3319 SPEC_USIGN(operandType(right)))) {
3320 // just an unsigned 8*8=8/16 multiply
3321 //emitcode (";","unsigned");
3322 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3323 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3324 emitcode ("mul", "ab");
3325 aopPut (AOP (result), "a", 0);
3327 aopPut (AOP (result), "b", 1);
3332 // we have to do a signed multiply
3334 //emitcode (";", "signed");
3335 emitcode ("clr", "F0"); // reset sign flag
3336 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3338 lbl=newiTempLabel(NULL);
3339 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3340 // left side is negative, 8-bit two's complement, this fails for -128
3341 emitcode ("setb", "F0"); // set sign flag
3342 emitcode ("cpl", "a");
3343 emitcode ("inc", "a");
3345 emitcode ("", "%05d$:", lbl->key+100);
3348 if (AOP_TYPE(right)==AOP_LIT) {
3349 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3350 /* AND literal negative */
3352 emitcode ("cpl", "F0"); // complement sign flag
3353 emitcode ("mov", "b,#0x%02x", -val);
3355 emitcode ("mov", "b,#0x%02x", val);
3358 lbl=newiTempLabel(NULL);
3359 emitcode ("mov", "b,a");
3360 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3361 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3362 // right side is negative, 8-bit two's complement
3363 emitcode ("cpl", "F0"); // complement sign flag
3364 emitcode ("cpl", "a");
3365 emitcode ("inc", "a");
3366 emitcode ("", "%05d$:", lbl->key+100);
3368 emitcode ("mul", "ab");
3370 lbl=newiTempLabel(NULL);
3371 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3372 // only ONE op was negative, we have to do a 8/16-bit two's complement
3373 emitcode ("cpl", "a"); // lsb
3375 emitcode ("inc", "a");
3377 emitcode ("add", "a,#1");
3378 emitcode ("xch", "a,b");
3379 emitcode ("cpl", "a"); // msb
3380 emitcode ("addc", "a,#0");
3381 emitcode ("xch", "a,b");
3384 emitcode ("", "%05d$:", lbl->key+100);
3385 aopPut (AOP (result), "a", 0);
3387 aopPut (AOP (result), "b", 1);
3391 /*-----------------------------------------------------------------*/
3392 /* genMult - generates code for multiplication */
3393 /*-----------------------------------------------------------------*/
3395 genMult (iCode * ic)
3397 operand *left = IC_LEFT (ic);
3398 operand *right = IC_RIGHT (ic);
3399 operand *result = IC_RESULT (ic);
3401 /* assign the amsops */
3402 aopOp (left, ic, FALSE);
3403 aopOp (right, ic, FALSE);
3404 aopOp (result, ic, TRUE);
3406 /* special cases first */
3408 if (AOP_TYPE (left) == AOP_CRY &&
3409 AOP_TYPE (right) == AOP_CRY)
3411 genMultbits (left, right, result);
3415 /* if both are of size == 1 */
3416 if (AOP_SIZE (left) == 1 &&
3417 AOP_SIZE (right) == 1)
3419 genMultOneByte (left, right, result);
3423 /* should have been converted to function call */
3427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3429 freeAsmop (result, NULL, ic, TRUE);
3432 /*-----------------------------------------------------------------*/
3433 /* genDivbits :- division of bits */
3434 /*-----------------------------------------------------------------*/
3436 genDivbits (operand * left,
3443 /* the result must be bit */
3444 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3445 l = aopGet (AOP (left), 0, FALSE, FALSE);
3449 emitcode ("div", "ab");
3450 emitcode ("rrc", "a");
3451 aopPut (AOP (result), "c", 0);
3454 /*-----------------------------------------------------------------*/
3455 /* genDivOneByte : 8 bit division */
3456 /*-----------------------------------------------------------------*/
3458 genDivOneByte (operand * left,
3462 sym_link *opetype = operandType (result);
3467 size = AOP_SIZE (result) - 1;
3469 /* signed or unsigned */
3470 if (SPEC_USIGN (opetype))
3472 /* unsigned is easy */
3473 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3474 l = aopGet (AOP (left), 0, FALSE, FALSE);
3476 emitcode ("div", "ab");
3477 aopPut (AOP (result), "a", 0);
3479 aopPut (AOP (result), zero, offset++);
3483 /* signed is a little bit more difficult */
3485 /* save the signs of the operands */
3486 l = aopGet (AOP (left), 0, FALSE, FALSE);
3488 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3489 emitcode ("push", "acc"); /* save it on the stack */
3491 /* now sign adjust for both left & right */
3492 l = aopGet (AOP (right), 0, FALSE, FALSE);
3494 lbl = newiTempLabel (NULL);
3495 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3496 emitcode ("cpl", "a");
3497 emitcode ("inc", "a");
3498 emitcode ("", "%05d$:", (lbl->key + 100));
3499 emitcode ("mov", "b,a");
3501 /* sign adjust left side */
3502 l = aopGet (AOP (left), 0, FALSE, FALSE);
3505 lbl = newiTempLabel (NULL);
3506 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3507 emitcode ("cpl", "a");
3508 emitcode ("inc", "a");
3509 emitcode ("", "%05d$:", (lbl->key + 100));
3511 /* now the division */
3512 emitcode ("div", "ab");
3513 /* we are interested in the lower order
3515 emitcode ("mov", "b,a");
3516 lbl = newiTempLabel (NULL);
3517 emitcode ("pop", "acc");
3518 /* if there was an over flow we don't
3519 adjust the sign of the result */
3520 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3521 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3523 emitcode ("clr", "a");
3524 emitcode ("subb", "a,b");
3525 emitcode ("mov", "b,a");
3526 emitcode ("", "%05d$:", (lbl->key + 100));
3528 /* now we are done */
3529 aopPut (AOP (result), "b", 0);
3532 emitcode ("mov", "c,b.7");
3533 emitcode ("subb", "a,acc");
3536 aopPut (AOP (result), "a", offset++);
3540 /*-----------------------------------------------------------------*/
3541 /* genDiv - generates code for division */
3542 /*-----------------------------------------------------------------*/
3546 operand *left = IC_LEFT (ic);
3547 operand *right = IC_RIGHT (ic);
3548 operand *result = IC_RESULT (ic);
3550 /* assign the amsops */
3551 aopOp (left, ic, FALSE);
3552 aopOp (right, ic, FALSE);
3553 aopOp (result, ic, TRUE);
3555 /* special cases first */
3557 if (AOP_TYPE (left) == AOP_CRY &&
3558 AOP_TYPE (right) == AOP_CRY)
3560 genDivbits (left, right, result);
3564 /* if both are of size == 1 */
3565 if (AOP_SIZE (left) == 1 &&
3566 AOP_SIZE (right) == 1)
3568 genDivOneByte (left, right, result);
3572 /* should have been converted to function call */
3575 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3577 freeAsmop (result, NULL, ic, TRUE);
3580 /*-----------------------------------------------------------------*/
3581 /* genModbits :- modulus of bits */
3582 /*-----------------------------------------------------------------*/
3584 genModbits (operand * left,
3591 /* the result must be bit */
3592 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3593 l = aopGet (AOP (left), 0, FALSE, FALSE);
3597 emitcode ("div", "ab");
3598 emitcode ("mov", "a,b");
3599 emitcode ("rrc", "a");
3600 aopPut (AOP (result), "c", 0);
3603 /*-----------------------------------------------------------------*/
3604 /* genModOneByte : 8 bit modulus */
3605 /*-----------------------------------------------------------------*/
3607 genModOneByte (operand * left,
3611 sym_link *opetype = operandType (result);
3615 /* signed or unsigned */
3616 if (SPEC_USIGN (opetype))
3618 /* unsigned is easy */
3619 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3620 l = aopGet (AOP (left), 0, FALSE, FALSE);
3622 emitcode ("div", "ab");
3623 aopPut (AOP (result), "b", 0);
3627 /* signed is a little bit more difficult */
3629 /* save the signs of the operands */
3630 l = aopGet (AOP (left), 0, FALSE, FALSE);
3633 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3634 emitcode ("push", "acc"); /* save it on the stack */
3636 /* now sign adjust for both left & right */
3637 l = aopGet (AOP (right), 0, FALSE, FALSE);
3640 lbl = newiTempLabel (NULL);
3641 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3642 emitcode ("cpl", "a");
3643 emitcode ("inc", "a");
3644 emitcode ("", "%05d$:", (lbl->key + 100));
3645 emitcode ("mov", "b,a");
3647 /* sign adjust left side */
3648 l = aopGet (AOP (left), 0, FALSE, FALSE);
3651 lbl = newiTempLabel (NULL);
3652 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3653 emitcode ("cpl", "a");
3654 emitcode ("inc", "a");
3655 emitcode ("", "%05d$:", (lbl->key + 100));
3657 /* now the multiplication */
3658 emitcode ("div", "ab");
3659 /* we are interested in the lower order
3661 lbl = newiTempLabel (NULL);
3662 emitcode ("pop", "acc");
3663 /* if there was an over flow we don't
3664 adjust the sign of the result */
3665 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3666 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3668 emitcode ("clr", "a");
3669 emitcode ("subb", "a,b");
3670 emitcode ("mov", "b,a");
3671 emitcode ("", "%05d$:", (lbl->key + 100));
3673 /* now we are done */
3674 aopPut (AOP (result), "b", 0);
3678 /*-----------------------------------------------------------------*/
3679 /* genMod - generates code for division */
3680 /*-----------------------------------------------------------------*/
3684 operand *left = IC_LEFT (ic);
3685 operand *right = IC_RIGHT (ic);
3686 operand *result = IC_RESULT (ic);
3688 /* assign the amsops */
3689 aopOp (left, ic, FALSE);
3690 aopOp (right, ic, FALSE);
3691 aopOp (result, ic, TRUE);
3693 /* special cases first */
3695 if (AOP_TYPE (left) == AOP_CRY &&
3696 AOP_TYPE (right) == AOP_CRY)
3698 genModbits (left, right, result);
3702 /* if both are of size == 1 */
3703 if (AOP_SIZE (left) == 1 &&
3704 AOP_SIZE (right) == 1)
3706 genModOneByte (left, right, result);
3710 /* should have been converted to function call */
3714 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3715 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3716 freeAsmop (result, NULL, ic, TRUE);
3719 /*-----------------------------------------------------------------*/
3720 /* genIfxJump :- will create a jump depending on the ifx */
3721 /*-----------------------------------------------------------------*/
3723 genIfxJump (iCode * ic, char *jval)
3726 symbol *tlbl = newiTempLabel (NULL);
3729 /* if true label then we jump if condition
3733 jlbl = IC_TRUE (ic);
3734 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3735 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3739 /* false label is present */
3740 jlbl = IC_FALSE (ic);
3741 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3742 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3744 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3745 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3747 emitcode (inst, "%05d$", tlbl->key + 100);
3748 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3749 emitcode ("", "%05d$:", tlbl->key + 100);
3751 /* mark the icode as generated */
3755 /*-----------------------------------------------------------------*/
3756 /* genCmp :- greater or less than comparison */
3757 /*-----------------------------------------------------------------*/
3759 genCmp (operand * left, operand * right,
3760 operand * result, iCode * ifx, int sign, iCode *ic)
3762 int size, offset = 0;
3763 unsigned long lit = 0L;
3765 /* if left & right are bit variables */
3766 if (AOP_TYPE (left) == AOP_CRY &&
3767 AOP_TYPE (right) == AOP_CRY)
3769 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3770 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3774 /* subtract right from left if at the
3775 end the carry flag is set then we know that
3776 left is greater than right */
3777 size = max (AOP_SIZE (left), AOP_SIZE (right));
3779 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3780 if ((size == 1) && !sign &&
3781 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3783 symbol *lbl = newiTempLabel (NULL);
3784 emitcode ("cjne", "%s,%s,%05d$",
3785 aopGet (AOP (left), offset, FALSE, FALSE),
3786 aopGet (AOP (right), offset, FALSE, FALSE),
3788 emitcode ("", "%05d$:", lbl->key + 100);
3792 if (AOP_TYPE (right) == AOP_LIT)
3794 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3795 /* optimize if(x < 0) or if(x >= 0) */
3804 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3805 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3807 genIfxJump (ifx, "acc.7");
3811 emitcode ("rlc", "a");
3819 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3820 if (sign && size == 0)
3822 emitcode ("xrl", "a,#0x80");
3823 if (AOP_TYPE (right) == AOP_LIT)
3825 unsigned long lit = (unsigned long)
3826 floatFromVal (AOP (right)->aopu.aop_lit);
3827 emitcode ("subb", "a,#0x%02x",
3828 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3832 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3833 emitcode ("xrl", "b,#0x80");
3834 emitcode ("subb", "a,b");
3838 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3844 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3846 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3852 /* if the result is used in the next
3853 ifx conditional branch then generate
3854 code a little differently */
3856 genIfxJump (ifx, "c");
3859 /* leave the result in acc */
3863 /*-----------------------------------------------------------------*/
3864 /* genCmpGt :- greater than comparison */
3865 /*-----------------------------------------------------------------*/
3867 genCmpGt (iCode * ic, iCode * ifx)
3869 operand *left, *right, *result;
3870 sym_link *letype, *retype;
3873 left = IC_LEFT (ic);
3874 right = IC_RIGHT (ic);
3875 result = IC_RESULT (ic);
3877 letype = getSpec (operandType (left));
3878 retype = getSpec (operandType (right));
3879 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3880 /* assign the amsops */
3881 aopOp (left, ic, FALSE);
3882 aopOp (right, ic, FALSE);
3883 aopOp (result, ic, TRUE);
3885 genCmp (right, left, result, ifx, sign,ic);
3887 freeAsmop (result, NULL, ic, TRUE);
3890 /*-----------------------------------------------------------------*/
3891 /* genCmpLt - less than comparisons */
3892 /*-----------------------------------------------------------------*/
3894 genCmpLt (iCode * ic, iCode * ifx)
3896 operand *left, *right, *result;
3897 sym_link *letype, *retype;
3900 left = IC_LEFT (ic);
3901 right = IC_RIGHT (ic);
3902 result = IC_RESULT (ic);
3904 letype = getSpec (operandType (left));
3905 retype = getSpec (operandType (right));
3906 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3908 /* assign the amsops */
3909 aopOp (left, ic, FALSE);
3910 aopOp (right, ic, FALSE);
3911 aopOp (result, ic, TRUE);
3913 genCmp (left, right, result, ifx, sign,ic);
3915 freeAsmop (result, NULL, ic, TRUE);
3918 /*-----------------------------------------------------------------*/
3919 /* gencjneshort - compare and jump if not equal */
3920 /*-----------------------------------------------------------------*/
3922 gencjneshort (operand * left, operand * right, symbol * lbl)
3924 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3926 unsigned long lit = 0L;
3928 /* if the left side is a literal or
3929 if the right is in a pointer register and left
3931 if ((AOP_TYPE (left) == AOP_LIT) ||
3932 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3938 if (AOP_TYPE (right) == AOP_LIT)
3939 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3941 /* if the right side is a literal then anything goes */
3942 if (AOP_TYPE (right) == AOP_LIT &&
3943 AOP_TYPE (left) != AOP_DIR)
3947 emitcode ("cjne", "%s,%s,%05d$",
3948 aopGet (AOP (left), offset, FALSE, FALSE),
3949 aopGet (AOP (right), offset, FALSE, FALSE),
3955 /* if the right side is in a register or in direct space or
3956 if the left is a pointer register & right is not */
3957 else if (AOP_TYPE (right) == AOP_REG ||
3958 AOP_TYPE (right) == AOP_DIR ||
3959 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3960 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3964 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3965 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3966 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3967 emitcode ("jnz", "%05d$", lbl->key + 100);
3969 emitcode ("cjne", "a,%s,%05d$",
3970 aopGet (AOP (right), offset, FALSE, TRUE),
3977 /* right is a pointer reg need both a & b */
3980 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3981 if (strcmp (l, "b"))
3982 emitcode ("mov", "b,%s", l);
3983 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3984 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3990 /*-----------------------------------------------------------------*/
3991 /* gencjne - compare and jump if not equal */
3992 /*-----------------------------------------------------------------*/
3994 gencjne (operand * left, operand * right, symbol * lbl)
3996 symbol *tlbl = newiTempLabel (NULL);
3998 gencjneshort (left, right, lbl);
4000 emitcode ("mov", "a,%s", one);
4001 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4002 emitcode ("", "%05d$:", lbl->key + 100);
4003 emitcode ("clr", "a");
4004 emitcode ("", "%05d$:", tlbl->key + 100);
4007 /*-----------------------------------------------------------------*/
4008 /* genCmpEq - generates code for equal to */
4009 /*-----------------------------------------------------------------*/
4011 genCmpEq (iCode * ic, iCode * ifx)
4013 operand *left, *right, *result;
4015 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4016 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4017 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4019 /* if literal, literal on the right or
4020 if the right is in a pointer register and left
4022 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4023 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4025 operand *t = IC_RIGHT (ic);
4026 IC_RIGHT (ic) = IC_LEFT (ic);
4030 if (ifx && !AOP_SIZE (result))
4033 /* if they are both bit variables */
4034 if (AOP_TYPE (left) == AOP_CRY &&
4035 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4037 if (AOP_TYPE (right) == AOP_LIT)
4039 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4043 emitcode ("cpl", "c");
4047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4051 emitcode ("clr", "c");
4053 /* AOP_TYPE(right) == AOP_CRY */
4057 symbol *lbl = newiTempLabel (NULL);
4058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4059 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4060 emitcode ("cpl", "c");
4061 emitcode ("", "%05d$:", (lbl->key + 100));
4063 /* if true label then we jump if condition
4065 tlbl = newiTempLabel (NULL);
4068 emitcode ("jnc", "%05d$", tlbl->key + 100);
4069 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4073 emitcode ("jc", "%05d$", tlbl->key + 100);
4074 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4076 emitcode ("", "%05d$:", tlbl->key + 100);
4080 tlbl = newiTempLabel (NULL);
4081 gencjneshort (left, right, tlbl);
4084 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4085 emitcode ("", "%05d$:", tlbl->key + 100);
4089 symbol *lbl = newiTempLabel (NULL);
4090 emitcode ("sjmp", "%05d$", lbl->key + 100);
4091 emitcode ("", "%05d$:", tlbl->key + 100);
4092 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4093 emitcode ("", "%05d$:", lbl->key + 100);
4096 /* mark the icode as generated */
4101 /* if they are both bit variables */
4102 if (AOP_TYPE (left) == AOP_CRY &&
4103 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4105 if (AOP_TYPE (right) == AOP_LIT)
4107 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4110 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4111 emitcode ("cpl", "c");
4115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4119 emitcode ("clr", "c");
4121 /* AOP_TYPE(right) == AOP_CRY */
4125 symbol *lbl = newiTempLabel (NULL);
4126 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4127 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4128 emitcode ("cpl", "c");
4129 emitcode ("", "%05d$:", (lbl->key + 100));
4132 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4139 genIfxJump (ifx, "c");
4142 /* if the result is used in an arithmetic operation
4143 then put the result in place */
4148 gencjne (left, right, newiTempLabel (NULL));
4149 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4151 aopPut (AOP (result), "a", 0);
4156 genIfxJump (ifx, "a");
4159 /* if the result is used in an arithmetic operation
4160 then put the result in place */
4161 if (AOP_TYPE (result) != AOP_CRY)
4163 /* leave the result in acc */
4167 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4168 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4169 freeAsmop (result, NULL, ic, TRUE);
4172 /*-----------------------------------------------------------------*/
4173 /* ifxForOp - returns the icode containing the ifx for operand */
4174 /*-----------------------------------------------------------------*/
4176 ifxForOp (operand * op, iCode * ic)
4178 /* if true symbol then needs to be assigned */
4179 if (IS_TRUE_SYMOP (op))
4182 /* if this has register type condition and
4183 the next instruction is ifx with the same operand
4184 and live to of the operand is upto the ifx only then */
4186 ic->next->op == IFX &&
4187 IC_COND (ic->next)->key == op->key &&
4188 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4194 /*-----------------------------------------------------------------*/
4195 /* hasInc - operand is incremented before any other use */
4196 /*-----------------------------------------------------------------*/
4198 hasInc (operand *op, iCode *ic)
4200 sym_link *type = operandType(op);
4201 sym_link *retype = getSpec (type);
4202 iCode *lic = ic->next;
4205 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4206 isize = getSize(type->next);
4208 /* if operand of the form op = op + <sizeof *op> */
4209 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4210 isOperandEqual(IC_RESULT(lic),op) &&
4211 isOperandLiteral(IC_RIGHT(lic)) &&
4212 operandLitValue(IC_RIGHT(lic)) == isize) {
4215 /* if the operand used or deffed */
4216 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4224 /*-----------------------------------------------------------------*/
4225 /* genAndOp - for && operation */
4226 /*-----------------------------------------------------------------*/
4228 genAndOp (iCode * ic)
4230 operand *left, *right, *result;
4233 /* note here that && operations that are in an
4234 if statement are taken away by backPatchLabels
4235 only those used in arthmetic operations remain */
4236 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4237 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4238 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4240 /* if both are bit variables */
4241 if (AOP_TYPE (left) == AOP_CRY &&
4242 AOP_TYPE (right) == AOP_CRY)
4244 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4245 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4250 tlbl = newiTempLabel (NULL);
4252 emitcode ("jz", "%05d$", tlbl->key + 100);
4254 emitcode ("", "%05d$:", tlbl->key + 100);
4258 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4259 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260 freeAsmop (result, NULL, ic, TRUE);
4264 /*-----------------------------------------------------------------*/
4265 /* genOrOp - for || operation */
4266 /*-----------------------------------------------------------------*/
4268 genOrOp (iCode * ic)
4270 operand *left, *right, *result;
4273 /* note here that || operations that are in an
4274 if statement are taken away by backPatchLabels
4275 only those used in arthmetic operations remain */
4276 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4277 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4278 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4280 /* if both are bit variables */
4281 if (AOP_TYPE (left) == AOP_CRY &&
4282 AOP_TYPE (right) == AOP_CRY)
4284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4285 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4290 tlbl = newiTempLabel (NULL);
4292 emitcode ("jnz", "%05d$", tlbl->key + 100);
4294 emitcode ("", "%05d$:", tlbl->key + 100);
4298 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4300 freeAsmop (result, NULL, ic, TRUE);
4303 /*-----------------------------------------------------------------*/
4304 /* isLiteralBit - test if lit == 2^n */
4305 /*-----------------------------------------------------------------*/
4307 isLiteralBit (unsigned long lit)
4309 unsigned long pw[32] =
4310 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4311 0x100L, 0x200L, 0x400L, 0x800L,
4312 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4313 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4314 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4315 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4316 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4319 for (idx = 0; idx < 32; idx++)
4325 /*-----------------------------------------------------------------*/
4326 /* continueIfTrue - */
4327 /*-----------------------------------------------------------------*/
4329 continueIfTrue (iCode * ic)
4332 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4336 /*-----------------------------------------------------------------*/
4338 /*-----------------------------------------------------------------*/
4340 jumpIfTrue (iCode * ic)
4343 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4347 /*-----------------------------------------------------------------*/
4348 /* jmpTrueOrFalse - */
4349 /*-----------------------------------------------------------------*/
4351 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4353 // ugly but optimized by peephole
4356 symbol *nlbl = newiTempLabel (NULL);
4357 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4358 emitcode ("", "%05d$:", tlbl->key + 100);
4359 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4360 emitcode ("", "%05d$:", nlbl->key + 100);
4364 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4365 emitcode ("", "%05d$:", tlbl->key + 100);
4370 /*-----------------------------------------------------------------*/
4371 /* genAnd - code for and */
4372 /*-----------------------------------------------------------------*/
4374 genAnd (iCode * ic, iCode * ifx)
4376 operand *left, *right, *result;
4377 int size, offset = 0;
4378 unsigned long lit = 0L;
4382 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4383 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4384 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4387 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4389 AOP_TYPE (left), AOP_TYPE (right));
4390 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4392 AOP_SIZE (left), AOP_SIZE (right));
4395 /* if left is a literal & right is not then exchange them */
4396 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4397 AOP_NEEDSACC (left))
4399 operand *tmp = right;
4404 /* if result = right then exchange them */
4405 if (sameRegs (AOP (result), AOP (right)))
4407 operand *tmp = right;
4412 /* if right is bit then exchange them */
4413 if (AOP_TYPE (right) == AOP_CRY &&
4414 AOP_TYPE (left) != AOP_CRY)
4416 operand *tmp = right;
4420 if (AOP_TYPE (right) == AOP_LIT)
4421 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4423 size = AOP_SIZE (result);
4426 // result = bit & yy;
4427 if (AOP_TYPE (left) == AOP_CRY)
4429 // c = bit & literal;
4430 if (AOP_TYPE (right) == AOP_LIT)
4434 if (size && sameRegs (AOP (result), AOP (left)))
4437 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4442 if (size && (AOP_TYPE (result) == AOP_CRY))
4444 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4447 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4452 emitcode ("clr", "c");
4457 if (AOP_TYPE (right) == AOP_CRY)
4460 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4461 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4466 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4468 emitcode ("rrc", "a");
4469 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4477 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4478 genIfxJump (ifx, "c");
4482 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4483 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4484 if ((AOP_TYPE (right) == AOP_LIT) &&
4485 (AOP_TYPE (result) == AOP_CRY) &&
4486 (AOP_TYPE (left) != AOP_CRY))
4488 int posbit = isLiteralBit (lit);
4493 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4496 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4502 sprintf (buffer, "acc.%d", posbit & 0x07);
4503 genIfxJump (ifx, buffer);
4510 symbol *tlbl = newiTempLabel (NULL);
4511 int sizel = AOP_SIZE (left);
4513 emitcode ("setb", "c");
4516 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4518 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4520 if ((posbit = isLiteralBit (bytelit)) != 0)
4521 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4524 if (bytelit != 0x0FFL)
4525 emitcode ("anl", "a,%s",
4526 aopGet (AOP (right), offset, FALSE, TRUE));
4527 emitcode ("jnz", "%05d$", tlbl->key + 100);
4532 // bit = left & literal
4535 emitcode ("clr", "c");
4536 emitcode ("", "%05d$:", tlbl->key + 100);
4538 // if(left & literal)
4542 jmpTrueOrFalse (ifx, tlbl);
4550 /* if left is same as result */
4551 if (sameRegs (AOP (result), AOP (left)))
4553 for (; size--; offset++)
4555 if (AOP_TYPE (right) == AOP_LIT)
4557 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4559 else if (bytelit == 0)
4560 aopPut (AOP (result), zero, offset);
4561 else if (IS_AOP_PREG (result))
4563 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4564 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4565 aopPut (AOP (result), "a", offset);
4568 emitcode ("anl", "%s,%s",
4569 aopGet (AOP (left), offset, FALSE, TRUE),
4570 aopGet (AOP (right), offset, FALSE, FALSE));
4574 if (AOP_TYPE (left) == AOP_ACC)
4575 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4578 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4579 if (IS_AOP_PREG (result))
4581 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4582 aopPut (AOP (result), "a", offset);
4586 emitcode ("anl", "%s,a",
4587 aopGet (AOP (left), offset, FALSE, TRUE));
4594 // left & result in different registers
4595 if (AOP_TYPE (result) == AOP_CRY)
4598 // if(size), result in bit
4599 // if(!size && ifx), conditional oper: if(left & right)
4600 symbol *tlbl = newiTempLabel (NULL);
4601 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4603 emitcode ("setb", "c");
4606 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4607 emitcode ("anl", "a,%s",
4608 aopGet (AOP (right), offset, FALSE, FALSE));
4610 if (AOP_TYPE(left)==AOP_ACC) {
4611 emitcode("mov", "b,a");
4612 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4613 emitcode("anl", "a,b");
4615 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4616 emitcode ("anl", "a,%s",
4617 aopGet (AOP (left), offset, FALSE, FALSE));
4620 emitcode ("jnz", "%05d$", tlbl->key + 100);
4626 emitcode ("", "%05d$:", tlbl->key + 100);
4630 jmpTrueOrFalse (ifx, tlbl);
4634 for (; (size--); offset++)
4637 // result = left & right
4638 if (AOP_TYPE (right) == AOP_LIT)
4640 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4642 aopPut (AOP (result),
4643 aopGet (AOP (left), offset, FALSE, FALSE),
4647 else if (bytelit == 0)
4649 aopPut (AOP (result), zero, offset);
4653 // faster than result <- left, anl result,right
4654 // and better if result is SFR
4655 if (AOP_TYPE (left) == AOP_ACC)
4656 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4659 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4660 emitcode ("anl", "a,%s",
4661 aopGet (AOP (left), offset, FALSE, FALSE));
4663 aopPut (AOP (result), "a", offset);
4669 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4670 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4671 freeAsmop (result, NULL, ic, TRUE);
4674 /*-----------------------------------------------------------------*/
4675 /* genOr - code for or */
4676 /*-----------------------------------------------------------------*/
4678 genOr (iCode * ic, iCode * ifx)
4680 operand *left, *right, *result;
4681 int size, offset = 0;
4682 unsigned long lit = 0L;
4684 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4685 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4686 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4689 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4691 AOP_TYPE (left), AOP_TYPE (right));
4692 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4694 AOP_SIZE (left), AOP_SIZE (right));
4697 /* if left is a literal & right is not then exchange them */
4698 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4699 AOP_NEEDSACC (left))
4701 operand *tmp = right;
4706 /* if result = right then exchange them */
4707 if (sameRegs (AOP (result), AOP (right)))
4709 operand *tmp = right;
4714 /* if right is bit then exchange them */
4715 if (AOP_TYPE (right) == AOP_CRY &&
4716 AOP_TYPE (left) != AOP_CRY)
4718 operand *tmp = right;
4722 if (AOP_TYPE (right) == AOP_LIT)
4723 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4725 size = AOP_SIZE (result);
4729 if (AOP_TYPE (left) == AOP_CRY)
4731 if (AOP_TYPE (right) == AOP_LIT)
4733 // c = bit & literal;
4736 // lit != 0 => result = 1
4737 if (AOP_TYPE (result) == AOP_CRY)
4740 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4742 continueIfTrue (ifx);
4745 emitcode ("setb", "c");
4749 // lit == 0 => result = left
4750 if (size && sameRegs (AOP (result), AOP (left)))
4752 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4757 if (AOP_TYPE (right) == AOP_CRY)
4760 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4761 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4766 symbol *tlbl = newiTempLabel (NULL);
4767 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4768 emitcode ("setb", "c");
4769 emitcode ("jb", "%s,%05d$",
4770 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4772 emitcode ("jnz", "%05d$", tlbl->key + 100);
4773 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4775 jmpTrueOrFalse (ifx, tlbl);
4781 emitcode ("", "%05d$:", tlbl->key + 100);
4790 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4791 genIfxJump (ifx, "c");
4795 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4796 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4797 if ((AOP_TYPE (right) == AOP_LIT) &&
4798 (AOP_TYPE (result) == AOP_CRY) &&
4799 (AOP_TYPE (left) != AOP_CRY))
4805 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4807 continueIfTrue (ifx);
4812 // lit = 0, result = boolean(left)
4814 emitcode ("setb", "c");
4818 symbol *tlbl = newiTempLabel (NULL);
4819 emitcode ("jnz", "%05d$", tlbl->key + 100);
4821 emitcode ("", "%05d$:", tlbl->key + 100);
4825 genIfxJump (ifx, "a");
4833 /* if left is same as result */
4834 if (sameRegs (AOP (result), AOP (left)))
4836 for (; size--; offset++)
4838 if (AOP_TYPE (right) == AOP_LIT)
4840 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4842 else if (IS_AOP_PREG (left))
4844 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4845 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4846 aopPut (AOP (result), "a", offset);
4849 emitcode ("orl", "%s,%s",
4850 aopGet (AOP (left), offset, FALSE, TRUE),
4851 aopGet (AOP (right), offset, FALSE, FALSE));
4855 if (AOP_TYPE (left) == AOP_ACC)
4856 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4859 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4860 if (IS_AOP_PREG (left))
4862 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4863 aopPut (AOP (result), "a", offset);
4866 emitcode ("orl", "%s,a",
4867 aopGet (AOP (left), offset, FALSE, TRUE));
4874 // left & result in different registers
4875 if (AOP_TYPE (result) == AOP_CRY)
4878 // if(size), result in bit
4879 // if(!size && ifx), conditional oper: if(left | right)
4880 symbol *tlbl = newiTempLabel (NULL);
4881 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4883 emitcode ("setb", "c");
4886 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4887 emitcode ("orl", "a,%s",
4888 aopGet (AOP (right), offset, FALSE, FALSE));
4890 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4891 emitcode ("orl", "a,%s",
4892 aopGet (AOP (left), offset, FALSE, FALSE));
4894 emitcode ("jnz", "%05d$", tlbl->key + 100);
4900 emitcode ("", "%05d$:", tlbl->key + 100);
4904 jmpTrueOrFalse (ifx, tlbl);
4907 for (; (size--); offset++)
4910 // result = left & right
4911 if (AOP_TYPE (right) == AOP_LIT)
4913 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4915 aopPut (AOP (result),
4916 aopGet (AOP (left), offset, FALSE, FALSE),
4921 // faster than result <- left, anl result,right
4922 // and better if result is SFR
4923 if (AOP_TYPE (left) == AOP_ACC)
4924 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4927 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4928 emitcode ("orl", "a,%s",
4929 aopGet (AOP (left), offset, FALSE, FALSE));
4931 aopPut (AOP (result), "a", offset);
4936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (result, NULL, ic, TRUE);
4941 /*-----------------------------------------------------------------*/
4942 /* genXor - code for xclusive or */
4943 /*-----------------------------------------------------------------*/
4945 genXor (iCode * ic, iCode * ifx)
4947 operand *left, *right, *result;
4948 int size, offset = 0;
4949 unsigned long lit = 0L;
4951 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4952 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4953 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4956 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4958 AOP_TYPE (left), AOP_TYPE (right));
4959 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4961 AOP_SIZE (left), AOP_SIZE (right));
4964 /* if left is a literal & right is not ||
4965 if left needs acc & right does not */
4966 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4967 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4969 operand *tmp = right;
4974 /* if result = right then exchange them */
4975 if (sameRegs (AOP (result), AOP (right)))
4977 operand *tmp = right;
4982 /* if right is bit then exchange them */
4983 if (AOP_TYPE (right) == AOP_CRY &&
4984 AOP_TYPE (left) != AOP_CRY)
4986 operand *tmp = right;
4990 if (AOP_TYPE (right) == AOP_LIT)
4991 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4993 size = AOP_SIZE (result);
4997 if (AOP_TYPE (left) == AOP_CRY)
4999 if (AOP_TYPE (right) == AOP_LIT)
5001 // c = bit & literal;
5004 // lit>>1 != 0 => result = 1
5005 if (AOP_TYPE (result) == AOP_CRY)
5008 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5010 continueIfTrue (ifx);
5013 emitcode ("setb", "c");
5020 // lit == 0, result = left
5021 if (size && sameRegs (AOP (result), AOP (left)))
5023 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5027 // lit == 1, result = not(left)
5028 if (size && sameRegs (AOP (result), AOP (left)))
5030 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5035 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5036 emitcode ("cpl", "c");
5045 symbol *tlbl = newiTempLabel (NULL);
5046 if (AOP_TYPE (right) == AOP_CRY)
5049 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5053 int sizer = AOP_SIZE (right);
5055 // if val>>1 != 0, result = 1
5056 emitcode ("setb", "c");
5059 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5061 // test the msb of the lsb
5062 emitcode ("anl", "a,#0xfe");
5063 emitcode ("jnz", "%05d$", tlbl->key + 100);
5067 emitcode ("rrc", "a");
5069 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5070 emitcode ("cpl", "c");
5071 emitcode ("", "%05d$:", (tlbl->key + 100));
5078 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5079 genIfxJump (ifx, "c");
5083 if (sameRegs (AOP (result), AOP (left)))
5085 /* if left is same as result */
5086 for (; size--; offset++)
5088 if (AOP_TYPE (right) == AOP_LIT)
5090 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5092 else if (IS_AOP_PREG (left))
5094 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5095 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5096 aopPut (AOP (result), "a", offset);
5099 emitcode ("xrl", "%s,%s",
5100 aopGet (AOP (left), offset, FALSE, TRUE),
5101 aopGet (AOP (right), offset, FALSE, FALSE));
5105 if (AOP_TYPE (left) == AOP_ACC)
5106 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5109 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5110 if (IS_AOP_PREG (left))
5112 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5113 aopPut (AOP (result), "a", offset);
5116 emitcode ("xrl", "%s,a",
5117 aopGet (AOP (left), offset, FALSE, TRUE));
5124 // left & result in different registers
5125 if (AOP_TYPE (result) == AOP_CRY)
5128 // if(size), result in bit
5129 // if(!size && ifx), conditional oper: if(left ^ right)
5130 symbol *tlbl = newiTempLabel (NULL);
5131 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5133 emitcode ("setb", "c");
5136 if ((AOP_TYPE (right) == AOP_LIT) &&
5137 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5139 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5143 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5144 emitcode ("xrl", "a,%s",
5145 aopGet (AOP (right), offset, FALSE, FALSE));
5147 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5148 emitcode ("xrl", "a,%s",
5149 aopGet (AOP (left), offset, FALSE, FALSE));
5152 emitcode ("jnz", "%05d$", tlbl->key + 100);
5158 emitcode ("", "%05d$:", tlbl->key + 100);
5162 jmpTrueOrFalse (ifx, tlbl);
5165 for (; (size--); offset++)
5168 // result = left & right
5169 if (AOP_TYPE (right) == AOP_LIT)
5171 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5173 aopPut (AOP (result),
5174 aopGet (AOP (left), offset, FALSE, FALSE),
5179 // faster than result <- left, anl result,right
5180 // and better if result is SFR
5181 if (AOP_TYPE (left) == AOP_ACC)
5182 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5186 emitcode ("xrl", "a,%s",
5187 aopGet (AOP (left), offset, FALSE, TRUE));
5189 aopPut (AOP (result), "a", offset);
5194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196 freeAsmop (result, NULL, ic, TRUE);
5199 /*-----------------------------------------------------------------*/
5200 /* genInline - write the inline code out */
5201 /*-----------------------------------------------------------------*/
5203 genInline (iCode * ic)
5205 char *buffer, *bp, *bp1;
5207 _G.inLine += (!options.asmpeep);
5209 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5210 strcpy (buffer, IC_INLINE (ic));
5212 /* emit each line as a code */
5237 /* emitcode("",buffer); */
5238 _G.inLine -= (!options.asmpeep);
5241 /*-----------------------------------------------------------------*/
5242 /* genRRC - rotate right with carry */
5243 /*-----------------------------------------------------------------*/
5247 operand *left, *result;
5248 int size, offset = 0;
5251 /* rotate right with carry */
5252 left = IC_LEFT (ic);
5253 result = IC_RESULT (ic);
5254 aopOp (left, ic, FALSE);
5255 aopOp (result, ic, FALSE);
5257 /* move it to the result */
5258 size = AOP_SIZE (result);
5263 l = aopGet (AOP (left), offset, FALSE, FALSE);
5265 emitcode ("rrc", "a");
5266 if (AOP_SIZE (result) > 1)
5267 aopPut (AOP (result), "a", offset--);
5269 /* now we need to put the carry into the
5270 highest order byte of the result */
5271 if (AOP_SIZE (result) > 1)
5273 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5276 emitcode ("mov", "acc.7,c");
5277 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5278 freeAsmop (left, NULL, ic, TRUE);
5279 freeAsmop (result, NULL, ic, TRUE);
5282 /*-----------------------------------------------------------------*/
5283 /* genRLC - generate code for rotate left with carry */
5284 /*-----------------------------------------------------------------*/
5288 operand *left, *result;
5289 int size, offset = 0;
5292 /* rotate right with carry */
5293 left = IC_LEFT (ic);
5294 result = IC_RESULT (ic);
5295 aopOp (left, ic, FALSE);
5296 aopOp (result, ic, FALSE);
5298 /* move it to the result */
5299 size = AOP_SIZE (result);
5303 l = aopGet (AOP (left), offset, FALSE, FALSE);
5305 emitcode ("add", "a,acc");
5306 if (AOP_SIZE (result) > 1)
5307 aopPut (AOP (result), "a", offset++);
5310 l = aopGet (AOP (left), offset, FALSE, FALSE);
5312 emitcode ("rlc", "a");
5313 if (AOP_SIZE (result) > 1)
5314 aopPut (AOP (result), "a", offset++);
5317 /* now we need to put the carry into the
5318 highest order byte of the result */
5319 if (AOP_SIZE (result) > 1)
5321 l = aopGet (AOP (result), 0, FALSE, FALSE);
5324 emitcode ("mov", "acc.0,c");
5325 aopPut (AOP (result), "a", 0);
5326 freeAsmop (left, NULL, ic, TRUE);
5327 freeAsmop (result, NULL, ic, TRUE);
5330 /*-----------------------------------------------------------------*/
5331 /* genGetHbit - generates code get highest order bit */
5332 /*-----------------------------------------------------------------*/
5334 genGetHbit (iCode * ic)
5336 operand *left, *result;
5337 left = IC_LEFT (ic);
5338 result = IC_RESULT (ic);
5339 aopOp (left, ic, FALSE);
5340 aopOp (result, ic, FALSE);
5342 /* get the highest order byte into a */
5343 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5344 if (AOP_TYPE (result) == AOP_CRY)
5346 emitcode ("rlc", "a");
5351 emitcode ("rl", "a");
5352 emitcode ("anl", "a,#0x01");
5357 freeAsmop (left, NULL, ic, TRUE);
5358 freeAsmop (result, NULL, ic, TRUE);
5361 /*-----------------------------------------------------------------*/
5362 /* AccRol - rotate left accumulator by known count */
5363 /*-----------------------------------------------------------------*/
5365 AccRol (int shCount)
5367 shCount &= 0x0007; // shCount : 0..7
5374 emitcode ("rl", "a");
5377 emitcode ("rl", "a");
5378 emitcode ("rl", "a");
5381 emitcode ("swap", "a");
5382 emitcode ("rr", "a");
5385 emitcode ("swap", "a");
5388 emitcode ("swap", "a");
5389 emitcode ("rl", "a");
5392 emitcode ("rr", "a");
5393 emitcode ("rr", "a");
5396 emitcode ("rr", "a");
5401 /*-----------------------------------------------------------------*/
5402 /* AccLsh - left shift accumulator by known count */
5403 /*-----------------------------------------------------------------*/
5405 AccLsh (int shCount)
5410 emitcode ("add", "a,acc");
5411 else if (shCount == 2)
5413 emitcode ("add", "a,acc");
5414 emitcode ("add", "a,acc");
5418 /* rotate left accumulator */
5420 /* and kill the lower order bits */
5421 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5426 /*-----------------------------------------------------------------*/
5427 /* AccRsh - right shift accumulator by known count */
5428 /*-----------------------------------------------------------------*/
5430 AccRsh (int shCount)
5437 emitcode ("rrc", "a");
5441 /* rotate right accumulator */
5442 AccRol (8 - shCount);
5443 /* and kill the higher order bits */
5444 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5449 /*-----------------------------------------------------------------*/
5450 /* AccSRsh - signed right shift accumulator by known count */
5451 /*-----------------------------------------------------------------*/
5453 AccSRsh (int shCount)
5460 emitcode ("mov", "c,acc.7");
5461 emitcode ("rrc", "a");
5463 else if (shCount == 2)
5465 emitcode ("mov", "c,acc.7");
5466 emitcode ("rrc", "a");
5467 emitcode ("mov", "c,acc.7");
5468 emitcode ("rrc", "a");
5472 tlbl = newiTempLabel (NULL);
5473 /* rotate right accumulator */
5474 AccRol (8 - shCount);
5475 /* and kill the higher order bits */
5476 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5477 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5478 emitcode ("orl", "a,#0x%02x",
5479 (unsigned char) ~SRMask[shCount]);
5480 emitcode ("", "%05d$:", tlbl->key + 100);
5485 /*-----------------------------------------------------------------*/
5486 /* shiftR1Left2Result - shift right one byte from left to result */
5487 /*-----------------------------------------------------------------*/
5489 shiftR1Left2Result (operand * left, int offl,
5490 operand * result, int offr,
5491 int shCount, int sign)
5493 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5494 /* shift right accumulator */
5499 aopPut (AOP (result), "a", offr);
5502 /*-----------------------------------------------------------------*/
5503 /* shiftL1Left2Result - shift left one byte from left to result */
5504 /*-----------------------------------------------------------------*/
5506 shiftL1Left2Result (operand * left, int offl,
5507 operand * result, int offr, int shCount)
5510 l = aopGet (AOP (left), offl, FALSE, FALSE);
5512 /* shift left accumulator */
5514 aopPut (AOP (result), "a", offr);
5517 /*-----------------------------------------------------------------*/
5518 /* movLeft2Result - move byte from left to result */
5519 /*-----------------------------------------------------------------*/
5521 movLeft2Result (operand * left, int offl,
5522 operand * result, int offr, int sign)
5525 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5527 l = aopGet (AOP (left), offl, FALSE, FALSE);
5529 if (*l == '@' && (IS_AOP_PREG (result)))
5531 emitcode ("mov", "a,%s", l);
5532 aopPut (AOP (result), "a", offr);
5537 aopPut (AOP (result), l, offr);
5540 /* MSB sign in acc.7 ! */
5541 if (getDataSize (left) == offl + 1)
5543 emitcode ("mov", "a,%s", l);
5544 aopPut (AOP (result), "a", offr);
5551 /*-----------------------------------------------------------------*/
5552 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5553 /*-----------------------------------------------------------------*/
5557 emitcode ("rrc", "a");
5558 emitcode ("xch", "a,%s", x);
5559 emitcode ("rrc", "a");
5560 emitcode ("xch", "a,%s", x);
5563 /*-----------------------------------------------------------------*/
5564 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5565 /*-----------------------------------------------------------------*/
5569 emitcode ("xch", "a,%s", x);
5570 emitcode ("rlc", "a");
5571 emitcode ("xch", "a,%s", x);
5572 emitcode ("rlc", "a");
5575 /*-----------------------------------------------------------------*/
5576 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5577 /*-----------------------------------------------------------------*/
5581 emitcode ("xch", "a,%s", x);
5582 emitcode ("add", "a,acc");
5583 emitcode ("xch", "a,%s", x);
5584 emitcode ("rlc", "a");
5587 /*-----------------------------------------------------------------*/
5588 /* AccAXLsh - left shift a:x by known count (0..7) */
5589 /*-----------------------------------------------------------------*/
5591 AccAXLsh (char *x, int shCount)
5606 case 5: // AAAAABBB:CCCCCDDD
5608 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5610 emitcode ("anl", "a,#0x%02x",
5611 SLMask[shCount]); // BBB00000:CCCCCDDD
5613 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5615 AccRol (shCount); // DDDCCCCC:BBB00000
5617 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5619 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5621 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5623 emitcode ("anl", "a,#0x%02x",
5624 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5626 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5628 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5631 case 6: // AAAAAABB:CCCCCCDD
5632 emitcode ("anl", "a,#0x%02x",
5633 SRMask[shCount]); // 000000BB:CCCCCCDD
5634 emitcode ("mov", "c,acc.0"); // c = B
5635 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5637 AccAXRrl1 (x); // BCCCCCCD:D000000B
5638 AccAXRrl1 (x); // BBCCCCCC:DD000000
5640 emitcode("rrc","a");
5641 emitcode("xch","a,%s", x);
5642 emitcode("rrc","a");
5643 emitcode("mov","c,acc.0"); //<< get correct bit
5644 emitcode("xch","a,%s", x);
5646 emitcode("rrc","a");
5647 emitcode("xch","a,%s", x);
5648 emitcode("rrc","a");
5649 emitcode("xch","a,%s", x);
5652 case 7: // a:x <<= 7
5654 emitcode ("anl", "a,#0x%02x",
5655 SRMask[shCount]); // 0000000B:CCCCCCCD
5657 emitcode ("mov", "c,acc.0"); // c = B
5659 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5661 AccAXRrl1 (x); // BCCCCCCC:D0000000
5669 /*-----------------------------------------------------------------*/
5670 /* AccAXRsh - right shift a:x known count (0..7) */
5671 /*-----------------------------------------------------------------*/
5673 AccAXRsh (char *x, int shCount)
5681 AccAXRrl1 (x); // 0->a:x
5686 AccAXRrl1 (x); // 0->a:x
5689 AccAXRrl1 (x); // 0->a:x
5694 case 5: // AAAAABBB:CCCCCDDD = a:x
5696 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5698 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5700 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5702 emitcode ("anl", "a,#0x%02x",
5703 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5705 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5707 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5709 emitcode ("anl", "a,#0x%02x",
5710 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5712 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5714 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5716 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5719 case 6: // AABBBBBB:CCDDDDDD
5721 emitcode ("mov", "c,acc.7");
5722 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5724 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5726 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5728 emitcode ("anl", "a,#0x%02x",
5729 SRMask[shCount]); // 000000AA:BBBBBBCC
5732 case 7: // ABBBBBBB:CDDDDDDD
5734 emitcode ("mov", "c,acc.7"); // c = A
5736 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5738 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5740 emitcode ("anl", "a,#0x%02x",
5741 SRMask[shCount]); // 0000000A:BBBBBBBC
5749 /*-----------------------------------------------------------------*/
5750 /* AccAXRshS - right shift signed a:x known count (0..7) */
5751 /*-----------------------------------------------------------------*/
5753 AccAXRshS (char *x, int shCount)
5761 emitcode ("mov", "c,acc.7");
5762 AccAXRrl1 (x); // s->a:x
5766 emitcode ("mov", "c,acc.7");
5767 AccAXRrl1 (x); // s->a:x
5769 emitcode ("mov", "c,acc.7");
5770 AccAXRrl1 (x); // s->a:x
5775 case 5: // AAAAABBB:CCCCCDDD = a:x
5777 tlbl = newiTempLabel (NULL);
5778 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5780 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5782 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5784 emitcode ("anl", "a,#0x%02x",
5785 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5787 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5789 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5791 emitcode ("anl", "a,#0x%02x",
5792 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5794 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5796 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5798 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5800 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5801 emitcode ("orl", "a,#0x%02x",
5802 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5804 emitcode ("", "%05d$:", tlbl->key + 100);
5805 break; // SSSSAAAA:BBBCCCCC
5807 case 6: // AABBBBBB:CCDDDDDD
5809 tlbl = newiTempLabel (NULL);
5810 emitcode ("mov", "c,acc.7");
5811 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5813 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5815 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5817 emitcode ("anl", "a,#0x%02x",
5818 SRMask[shCount]); // 000000AA:BBBBBBCC
5820 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5821 emitcode ("orl", "a,#0x%02x",
5822 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5824 emitcode ("", "%05d$:", tlbl->key + 100);
5826 case 7: // ABBBBBBB:CDDDDDDD
5828 tlbl = newiTempLabel (NULL);
5829 emitcode ("mov", "c,acc.7"); // c = A
5831 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5833 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5835 emitcode ("anl", "a,#0x%02x",
5836 SRMask[shCount]); // 0000000A:BBBBBBBC
5838 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5839 emitcode ("orl", "a,#0x%02x",
5840 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5842 emitcode ("", "%05d$:", tlbl->key + 100);
5849 /*-----------------------------------------------------------------*/
5850 /* shiftL2Left2Result - shift left two bytes from left to result */
5851 /*-----------------------------------------------------------------*/
5853 shiftL2Left2Result (operand * left, int offl,
5854 operand * result, int offr, int shCount)
5856 if (sameRegs (AOP (result), AOP (left)) &&
5857 ((offl + MSB16) == offr))
5859 /* don't crash result[offr] */
5860 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5861 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5865 movLeft2Result (left, offl, result, offr, 0);
5866 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5868 /* ax << shCount (x = lsb(result)) */
5869 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5870 aopPut (AOP (result), "a", offr + MSB16);
5874 /*-----------------------------------------------------------------*/
5875 /* shiftR2Left2Result - shift right two bytes from left to result */
5876 /*-----------------------------------------------------------------*/
5878 shiftR2Left2Result (operand * left, int offl,
5879 operand * result, int offr,
5880 int shCount, int sign)
5882 if (sameRegs (AOP (result), AOP (left)) &&
5883 ((offl + MSB16) == offr))
5885 /* don't crash result[offr] */
5886 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5887 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5891 movLeft2Result (left, offl, result, offr, 0);
5892 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5894 /* a:x >> shCount (x = lsb(result)) */
5896 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5898 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5899 if (getDataSize (result) > 1)
5900 aopPut (AOP (result), "a", offr + MSB16);
5903 /*-----------------------------------------------------------------*/
5904 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5905 /*-----------------------------------------------------------------*/
5907 shiftLLeftOrResult (operand * left, int offl,
5908 operand * result, int offr, int shCount)
5910 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5911 /* shift left accumulator */
5913 /* or with result */
5914 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5915 /* back to result */
5916 aopPut (AOP (result), "a", offr);
5919 /*-----------------------------------------------------------------*/
5920 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5921 /*-----------------------------------------------------------------*/
5923 shiftRLeftOrResult (operand * left, int offl,
5924 operand * result, int offr, int shCount)
5926 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5927 /* shift right accumulator */
5929 /* or with result */
5930 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5931 /* back to result */
5932 aopPut (AOP (result), "a", offr);
5935 /*-----------------------------------------------------------------*/
5936 /* genlshOne - left shift a one byte quantity by known count */
5937 /*-----------------------------------------------------------------*/
5939 genlshOne (operand * result, operand * left, int shCount)
5941 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5944 /*-----------------------------------------------------------------*/
5945 /* genlshTwo - left shift two bytes by known amount != 0 */
5946 /*-----------------------------------------------------------------*/
5948 genlshTwo (operand * result, operand * left, int shCount)
5952 size = getDataSize (result);
5954 /* if shCount >= 8 */
5962 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5964 movLeft2Result (left, LSB, result, MSB16, 0);
5966 aopPut (AOP (result), zero, LSB);
5969 /* 1 <= shCount <= 7 */
5973 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5975 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5979 /*-----------------------------------------------------------------*/
5980 /* shiftLLong - shift left one long from left to result */
5981 /* offl = LSB or MSB16 */
5982 /*-----------------------------------------------------------------*/
5984 shiftLLong (operand * left, operand * result, int offr)
5987 int size = AOP_SIZE (result);
5989 if (size >= LSB + offr)
5991 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5993 emitcode ("add", "a,acc");
5994 if (sameRegs (AOP (left), AOP (result)) &&
5995 size >= MSB16 + offr && offr != LSB)
5996 emitcode ("xch", "a,%s",
5997 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5999 aopPut (AOP (result), "a", LSB + offr);
6002 if (size >= MSB16 + offr)
6004 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6006 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6009 emitcode ("rlc", "a");
6010 if (sameRegs (AOP (left), AOP (result)) &&
6011 size >= MSB24 + offr && offr != LSB)
6012 emitcode ("xch", "a,%s",
6013 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6015 aopPut (AOP (result), "a", MSB16 + offr);
6018 if (size >= MSB24 + offr)
6020 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6022 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6025 emitcode ("rlc", "a");
6026 if (sameRegs (AOP (left), AOP (result)) &&
6027 size >= MSB32 + offr && offr != LSB)
6028 emitcode ("xch", "a,%s",
6029 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6031 aopPut (AOP (result), "a", MSB24 + offr);
6034 if (size > MSB32 + offr)
6036 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6038 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6041 emitcode ("rlc", "a");
6042 aopPut (AOP (result), "a", MSB32 + offr);
6045 aopPut (AOP (result), zero, LSB);
6048 /*-----------------------------------------------------------------*/
6049 /* genlshFour - shift four byte by a known amount != 0 */
6050 /*-----------------------------------------------------------------*/
6052 genlshFour (operand * result, operand * left, int shCount)
6056 size = AOP_SIZE (result);
6058 /* if shifting more that 3 bytes */
6063 /* lowest order of left goes to the highest
6064 order of the destination */
6065 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6067 movLeft2Result (left, LSB, result, MSB32, 0);
6068 aopPut (AOP (result), zero, LSB);
6069 aopPut (AOP (result), zero, MSB16);
6070 aopPut (AOP (result), zero, MSB24);
6074 /* more than two bytes */
6075 else if (shCount >= 16)
6077 /* lower order two bytes goes to higher order two bytes */
6079 /* if some more remaining */
6081 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6084 movLeft2Result (left, MSB16, result, MSB32, 0);
6085 movLeft2Result (left, LSB, result, MSB24, 0);
6087 aopPut (AOP (result), zero, MSB16);
6088 aopPut (AOP (result), zero, LSB);
6092 /* if more than 1 byte */
6093 else if (shCount >= 8)
6095 /* lower order three bytes goes to higher order three bytes */
6100 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6102 movLeft2Result (left, LSB, result, MSB16, 0);
6108 movLeft2Result (left, MSB24, result, MSB32, 0);
6109 movLeft2Result (left, MSB16, result, MSB24, 0);
6110 movLeft2Result (left, LSB, result, MSB16, 0);
6111 aopPut (AOP (result), zero, LSB);
6113 else if (shCount == 1)
6114 shiftLLong (left, result, MSB16);
6117 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6118 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6119 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6120 aopPut (AOP (result), zero, LSB);
6125 /* 1 <= shCount <= 7 */
6126 else if (shCount <= 2)
6128 shiftLLong (left, result, LSB);
6130 shiftLLong (result, result, LSB);
6132 /* 3 <= shCount <= 7, optimize */
6135 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6136 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6137 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6141 /*-----------------------------------------------------------------*/
6142 /* genLeftShiftLiteral - left shifting by known count */
6143 /*-----------------------------------------------------------------*/
6145 genLeftShiftLiteral (operand * left,
6150 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6153 freeAsmop (right, NULL, ic, TRUE);
6155 aopOp (left, ic, FALSE);
6156 aopOp (result, ic, FALSE);
6158 size = getSize (operandType (result));
6161 emitcode ("; shift left ", "result %d, left %d", size,
6165 /* I suppose that the left size >= result size */
6170 movLeft2Result (left, size, result, size, 0);
6174 else if (shCount >= (size * 8))
6176 aopPut (AOP (result), zero, size);
6182 genlshOne (result, left, shCount);
6186 genlshTwo (result, left, shCount);
6190 genlshFour (result, left, shCount);
6193 fprintf(stderr, "*** ack! mystery literal shift!\n");
6197 freeAsmop (left, NULL, ic, TRUE);
6198 freeAsmop (result, NULL, ic, TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* genLeftShift - generates code for left shifting */
6203 /*-----------------------------------------------------------------*/
6205 genLeftShift (iCode * ic)
6207 operand *left, *right, *result;
6210 symbol *tlbl, *tlbl1;
6212 right = IC_RIGHT (ic);
6213 left = IC_LEFT (ic);
6214 result = IC_RESULT (ic);
6216 aopOp (right, ic, FALSE);
6218 /* if the shift count is known then do it
6219 as efficiently as possible */
6220 if (AOP_TYPE (right) == AOP_LIT)
6222 genLeftShiftLiteral (left, right, result, ic);
6226 /* shift count is unknown then we have to form
6227 a loop get the loop count in B : Note: we take
6228 only the lower order byte since shifting
6229 more that 32 bits make no sense anyway, ( the
6230 largest size of an object can be only 32 bits ) */
6232 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6233 emitcode ("inc", "b");
6234 freeAsmop (right, NULL, ic, TRUE);
6235 aopOp (left, ic, FALSE);
6236 aopOp (result, ic, FALSE);
6238 /* now move the left to the result if they are not the
6240 if (!sameRegs (AOP (left), AOP (result)) &&
6241 AOP_SIZE (result) > 1)
6244 size = AOP_SIZE (result);
6248 l = aopGet (AOP (left), offset, FALSE, TRUE);
6249 if (*l == '@' && (IS_AOP_PREG (result)))
6252 emitcode ("mov", "a,%s", l);
6253 aopPut (AOP (result), "a", offset);
6256 aopPut (AOP (result), l, offset);
6261 tlbl = newiTempLabel (NULL);
6262 size = AOP_SIZE (result);
6264 tlbl1 = newiTempLabel (NULL);
6266 /* if it is only one byte then */
6269 symbol *tlbl1 = newiTempLabel (NULL);
6271 l = aopGet (AOP (left), 0, FALSE, FALSE);
6273 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6274 emitcode ("", "%05d$:", tlbl->key + 100);
6275 emitcode ("add", "a,acc");
6276 emitcode ("", "%05d$:", tlbl1->key + 100);
6277 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6278 aopPut (AOP (result), "a", 0);
6282 reAdjustPreg (AOP (result));
6284 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6285 emitcode ("", "%05d$:", tlbl->key + 100);
6286 l = aopGet (AOP (result), offset, FALSE, FALSE);
6288 emitcode ("add", "a,acc");
6289 aopPut (AOP (result), "a", offset++);
6292 l = aopGet (AOP (result), offset, FALSE, FALSE);
6294 emitcode ("rlc", "a");
6295 aopPut (AOP (result), "a", offset++);
6297 reAdjustPreg (AOP (result));
6299 emitcode ("", "%05d$:", tlbl1->key + 100);
6300 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6302 freeAsmop (left, NULL, ic, TRUE);
6303 freeAsmop (result, NULL, ic, TRUE);
6306 /*-----------------------------------------------------------------*/
6307 /* genrshOne - right shift a one byte quantity by known count */
6308 /*-----------------------------------------------------------------*/
6310 genrshOne (operand * result, operand * left,
6311 int shCount, int sign)
6313 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6316 /*-----------------------------------------------------------------*/
6317 /* genrshTwo - right shift two bytes by known amount != 0 */
6318 /*-----------------------------------------------------------------*/
6320 genrshTwo (operand * result, operand * left,
6321 int shCount, int sign)
6323 /* if shCount >= 8 */
6328 shiftR1Left2Result (left, MSB16, result, LSB,
6331 movLeft2Result (left, MSB16, result, LSB, sign);
6332 addSign (result, MSB16, sign);
6335 /* 1 <= shCount <= 7 */
6337 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6340 /*-----------------------------------------------------------------*/
6341 /* shiftRLong - shift right one long from left to result */
6342 /* offl = LSB or MSB16 */
6343 /*-----------------------------------------------------------------*/
6345 shiftRLong (operand * left, int offl,
6346 operand * result, int sign)
6348 int isSameRegs=sameRegs(AOP(left),AOP(result));
6350 if (isSameRegs && offl>1) {
6351 // we are in big trouble, but this shouldn't happen
6352 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6355 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6360 emitcode ("rlc", "a");
6361 emitcode ("subb", "a,acc");
6362 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6364 aopPut (AOP(result), zero, MSB32);
6369 emitcode ("clr", "c");
6371 emitcode ("mov", "c,acc.7");
6374 emitcode ("rrc", "a");
6376 if (isSameRegs && offl==MSB16) {
6377 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6379 aopPut (AOP (result), "a", MSB32);
6380 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6383 emitcode ("rrc", "a");
6384 if (isSameRegs && offl==1) {
6385 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6387 aopPut (AOP (result), "a", MSB24);
6388 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6390 emitcode ("rrc", "a");
6391 aopPut (AOP (result), "a", MSB16 - offl);
6395 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6396 emitcode ("rrc", "a");
6397 aopPut (AOP (result), "a", LSB);
6401 /*-----------------------------------------------------------------*/
6402 /* genrshFour - shift four byte by a known amount != 0 */
6403 /*-----------------------------------------------------------------*/
6405 genrshFour (operand * result, operand * left,
6406 int shCount, int sign)
6408 /* if shifting more that 3 bytes */
6413 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6415 movLeft2Result (left, MSB32, result, LSB, sign);
6416 addSign (result, MSB16, sign);
6418 else if (shCount >= 16)
6422 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6425 movLeft2Result (left, MSB24, result, LSB, 0);
6426 movLeft2Result (left, MSB32, result, MSB16, sign);
6428 addSign (result, MSB24, sign);
6430 else if (shCount >= 8)
6434 shiftRLong (left, MSB16, result, sign);
6435 else if (shCount == 0)
6437 movLeft2Result (left, MSB16, result, LSB, 0);
6438 movLeft2Result (left, MSB24, result, MSB16, 0);
6439 movLeft2Result (left, MSB32, result, MSB24, sign);
6440 addSign (result, MSB32, sign);
6444 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6445 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6446 /* the last shift is signed */
6447 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6448 addSign (result, MSB32, sign);
6452 { /* 1 <= shCount <= 7 */
6455 shiftRLong (left, LSB, result, sign);
6457 shiftRLong (result, LSB, result, sign);
6461 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6462 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6463 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6468 /*-----------------------------------------------------------------*/
6469 /* genRightShiftLiteral - right shifting by known count */
6470 /*-----------------------------------------------------------------*/
6472 genRightShiftLiteral (operand * left,
6478 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6481 freeAsmop (right, NULL, ic, TRUE);
6483 aopOp (left, ic, FALSE);
6484 aopOp (result, ic, FALSE);
6487 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6491 size = getDataSize (left);
6492 /* test the LEFT size !!! */
6494 /* I suppose that the left size >= result size */
6497 size = getDataSize (result);
6499 movLeft2Result (left, size, result, size, 0);
6502 else if (shCount >= (size * 8))
6505 /* get sign in acc.7 */
6506 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6507 addSign (result, LSB, sign);
6514 genrshOne (result, left, shCount, sign);
6518 genrshTwo (result, left, shCount, sign);
6522 genrshFour (result, left, shCount, sign);
6528 freeAsmop (left, NULL, ic, TRUE);
6529 freeAsmop (result, NULL, ic, TRUE);
6533 /*-----------------------------------------------------------------*/
6534 /* genSignedRightShift - right shift of signed number */
6535 /*-----------------------------------------------------------------*/
6537 genSignedRightShift (iCode * ic)
6539 operand *right, *left, *result;
6542 symbol *tlbl, *tlbl1;
6544 /* we do it the hard way put the shift count in b
6545 and loop thru preserving the sign */
6547 right = IC_RIGHT (ic);
6548 left = IC_LEFT (ic);
6549 result = IC_RESULT (ic);
6551 aopOp (right, ic, FALSE);
6554 if (AOP_TYPE (right) == AOP_LIT)
6556 genRightShiftLiteral (left, right, result, ic, 1);
6559 /* shift count is unknown then we have to form
6560 a loop get the loop count in B : Note: we take
6561 only the lower order byte since shifting
6562 more that 32 bits make no sense anyway, ( the
6563 largest size of an object can be only 32 bits ) */
6565 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6566 emitcode ("inc", "b");
6567 freeAsmop (right, NULL, ic, TRUE);
6568 aopOp (left, ic, FALSE);
6569 aopOp (result, ic, FALSE);
6571 /* now move the left to the result if they are not the
6573 if (!sameRegs (AOP (left), AOP (result)) &&
6574 AOP_SIZE (result) > 1)
6577 size = AOP_SIZE (result);
6581 l = aopGet (AOP (left), offset, FALSE, TRUE);
6582 if (*l == '@' && IS_AOP_PREG (result))
6585 emitcode ("mov", "a,%s", l);
6586 aopPut (AOP (result), "a", offset);
6589 aopPut (AOP (result), l, offset);
6594 /* mov the highest order bit to OVR */
6595 tlbl = newiTempLabel (NULL);
6596 tlbl1 = newiTempLabel (NULL);
6598 size = AOP_SIZE (result);
6600 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6601 emitcode ("rlc", "a");
6602 emitcode ("mov", "ov,c");
6603 /* if it is only one byte then */
6606 l = aopGet (AOP (left), 0, FALSE, FALSE);
6608 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6609 emitcode ("", "%05d$:", tlbl->key + 100);
6610 emitcode ("mov", "c,ov");
6611 emitcode ("rrc", "a");
6612 emitcode ("", "%05d$:", tlbl1->key + 100);
6613 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6614 aopPut (AOP (result), "a", 0);
6618 reAdjustPreg (AOP (result));
6619 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6620 emitcode ("", "%05d$:", tlbl->key + 100);
6621 emitcode ("mov", "c,ov");
6624 l = aopGet (AOP (result), offset, FALSE, FALSE);
6626 emitcode ("rrc", "a");
6627 aopPut (AOP (result), "a", offset--);
6629 reAdjustPreg (AOP (result));
6630 emitcode ("", "%05d$:", tlbl1->key + 100);
6631 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6634 freeAsmop (left, NULL, ic, TRUE);
6635 freeAsmop (result, NULL, ic, TRUE);
6638 /*-----------------------------------------------------------------*/
6639 /* genRightShift - generate code for right shifting */
6640 /*-----------------------------------------------------------------*/
6642 genRightShift (iCode * ic)
6644 operand *right, *left, *result;
6648 symbol *tlbl, *tlbl1;
6650 /* if signed then we do it the hard way preserve the
6651 sign bit moving it inwards */
6652 retype = getSpec (operandType (IC_RESULT (ic)));
6654 if (!SPEC_USIGN (retype))
6656 genSignedRightShift (ic);
6660 /* signed & unsigned types are treated the same : i.e. the
6661 signed is NOT propagated inwards : quoting from the
6662 ANSI - standard : "for E1 >> E2, is equivalent to division
6663 by 2**E2 if unsigned or if it has a non-negative value,
6664 otherwise the result is implementation defined ", MY definition
6665 is that the sign does not get propagated */
6667 right = IC_RIGHT (ic);
6668 left = IC_LEFT (ic);
6669 result = IC_RESULT (ic);
6671 aopOp (right, ic, FALSE);
6673 /* if the shift count is known then do it
6674 as efficiently as possible */
6675 if (AOP_TYPE (right) == AOP_LIT)
6677 genRightShiftLiteral (left, right, result, ic, 0);
6681 /* shift count is unknown then we have to form
6682 a loop get the loop count in B : Note: we take
6683 only the lower order byte since shifting
6684 more that 32 bits make no sense anyway, ( the
6685 largest size of an object can be only 32 bits ) */
6687 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6688 emitcode ("inc", "b");
6689 freeAsmop (right, NULL, ic, TRUE);
6690 aopOp (left, ic, FALSE);
6691 aopOp (result, ic, FALSE);
6693 /* now move the left to the result if they are not the
6695 if (!sameRegs (AOP (left), AOP (result)) &&
6696 AOP_SIZE (result) > 1)
6699 size = AOP_SIZE (result);
6703 l = aopGet (AOP (left), offset, FALSE, TRUE);
6704 if (*l == '@' && IS_AOP_PREG (result))
6707 emitcode ("mov", "a,%s", l);
6708 aopPut (AOP (result), "a", offset);
6711 aopPut (AOP (result), l, offset);
6716 tlbl = newiTempLabel (NULL);
6717 tlbl1 = newiTempLabel (NULL);
6718 size = AOP_SIZE (result);
6721 /* if it is only one byte then */
6724 l = aopGet (AOP (left), 0, FALSE, FALSE);
6726 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6727 emitcode ("", "%05d$:", tlbl->key + 100);
6729 emitcode ("rrc", "a");
6730 emitcode ("", "%05d$:", tlbl1->key + 100);
6731 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6732 aopPut (AOP (result), "a", 0);
6736 reAdjustPreg (AOP (result));
6737 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6738 emitcode ("", "%05d$:", tlbl->key + 100);
6742 l = aopGet (AOP (result), offset, FALSE, FALSE);
6744 emitcode ("rrc", "a");
6745 aopPut (AOP (result), "a", offset--);
6747 reAdjustPreg (AOP (result));
6749 emitcode ("", "%05d$:", tlbl1->key + 100);
6750 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6753 freeAsmop (left, NULL, ic, TRUE);
6754 freeAsmop (result, NULL, ic, TRUE);
6757 /*-----------------------------------------------------------------*/
6758 /* genUnpackBits - generates code for unpacking bits */
6759 /*-----------------------------------------------------------------*/
6761 genUnpackBits (operand * result, char *rname, int ptype)
6769 etype = getSpec (operandType (result));
6770 rsize = getSize (operandType (result));
6771 /* read the first byte */
6777 emitcode ("mov", "a,@%s", rname);
6781 emitcode ("movx", "a,@%s", rname);
6785 emitcode ("movx", "a,@dptr");
6789 emitcode ("clr", "a");
6790 emitcode ("movc", "a,%s", "@a+dptr");
6794 emitcode ("lcall", "__gptrget");
6798 rlen = SPEC_BLEN (etype);
6800 /* if we have bitdisplacement then it fits */
6801 /* into this byte completely or if length is */
6802 /* less than a byte */
6803 if ((shCnt = SPEC_BSTR (etype)) ||
6804 (SPEC_BLEN (etype) <= 8))
6807 /* shift right acc */
6810 emitcode ("anl", "a,#0x%02x",
6811 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6812 aopPut (AOP (result), "a", offset++);
6816 /* bit field did not fit in a byte */
6817 aopPut (AOP (result), "a", offset++);
6826 emitcode ("inc", "%s", rname);
6827 emitcode ("mov", "a,@%s", rname);
6831 emitcode ("inc", "%s", rname);
6832 emitcode ("movx", "a,@%s", rname);
6836 emitcode ("inc", "dptr");
6837 emitcode ("movx", "a,@dptr");
6841 emitcode ("clr", "a");
6842 emitcode ("inc", "dptr");
6843 emitcode ("movc", "a", "@a+dptr");
6847 emitcode ("inc", "dptr");
6848 emitcode ("lcall", "__gptrget");
6853 /* if we are done */
6857 aopPut (AOP (result), "a", offset++);
6863 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6865 aopPut (AOP (result), "a", offset++);
6873 aopPut (AOP (result), zero, offset++);
6879 /*-----------------------------------------------------------------*/
6880 /* genDataPointerGet - generates code when ptr offset is known */
6881 /*-----------------------------------------------------------------*/
6883 genDataPointerGet (operand * left,
6889 int size, offset = 0;
6890 aopOp (result, ic, TRUE);
6892 /* get the string representation of the name */
6893 l = aopGet (AOP (left), 0, FALSE, TRUE);
6894 size = AOP_SIZE (result);
6898 sprintf (buffer, "(%s + %d)", l + 1, offset);
6900 sprintf (buffer, "%s", l + 1);
6901 aopPut (AOP (result), buffer, offset++);
6904 freeAsmop (left, NULL, ic, TRUE);
6905 freeAsmop (result, NULL, ic, TRUE);
6908 /*-----------------------------------------------------------------*/
6909 /* genNearPointerGet - emitcode for near pointer fetch */
6910 /*-----------------------------------------------------------------*/
6912 genNearPointerGet (operand * left,
6920 sym_link *rtype, *retype;
6921 sym_link *ltype = operandType (left);
6924 rtype = operandType (result);
6925 retype = getSpec (rtype);
6927 aopOp (left, ic, FALSE);
6929 /* if left is rematerialisable and
6930 result is not bit variable type and
6931 the left is pointer to data space i.e
6932 lower 128 bytes of space */
6933 if (AOP_TYPE (left) == AOP_IMMD &&
6934 !IS_BITVAR (retype) &&
6935 DCL_TYPE (ltype) == POINTER)
6937 genDataPointerGet (left, result, ic);
6941 /* if the value is already in a pointer register
6942 then don't need anything more */
6943 if (!AOP_INPREG (AOP (left)))
6945 /* otherwise get a free pointer register */
6947 preg = getFreePtr (ic, &aop, FALSE);
6948 emitcode ("mov", "%s,%s",
6950 aopGet (AOP (left), 0, FALSE, TRUE));
6954 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6956 aopOp (result, ic, FALSE);
6958 /* if bitfield then unpack the bits */
6959 if (IS_BITVAR (retype))
6960 genUnpackBits (result, rname, POINTER);
6963 /* we have can just get the values */
6964 int size = AOP_SIZE (result);
6969 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6972 emitcode ("mov", "a,@%s", rname);
6973 aopPut (AOP (result), "a", offset);
6977 sprintf (buffer, "@%s", rname);
6978 aopPut (AOP (result), buffer, offset);
6982 emitcode ("inc", "%s", rname);
6986 /* now some housekeeping stuff */
6987 if (aop) /* we had to allocate for this iCode */
6989 if (pi) { /* post increment present */
6990 aopPut(AOP ( left ),rname,0);
6992 freeAsmop (NULL, aop, ic, TRUE);
6996 /* we did not allocate which means left
6997 already in a pointer register, then
6998 if size > 0 && this could be used again
6999 we have to point it back to where it
7001 if ((AOP_SIZE (result) > 1 &&
7002 !OP_SYMBOL (left)->remat &&
7003 (OP_SYMBOL (left)->liveTo > ic->seq ||
7007 int size = AOP_SIZE (result) - 1;
7009 emitcode ("dec", "%s", rname);
7014 freeAsmop (left, NULL, ic, TRUE);
7015 freeAsmop (result, NULL, ic, TRUE);
7016 if (pi) pi->generated = 1;
7019 /*-----------------------------------------------------------------*/
7020 /* genPagedPointerGet - emitcode for paged pointer fetch */
7021 /*-----------------------------------------------------------------*/
7023 genPagedPointerGet (operand * left,
7031 sym_link *rtype, *retype;
7033 rtype = operandType (result);
7034 retype = getSpec (rtype);
7036 aopOp (left, ic, FALSE);
7038 /* if the value is already in a pointer register
7039 then don't need anything more */
7040 if (!AOP_INPREG (AOP (left)))
7042 /* otherwise get a free pointer register */
7044 preg = getFreePtr (ic, &aop, FALSE);
7045 emitcode ("mov", "%s,%s",
7047 aopGet (AOP (left), 0, FALSE, TRUE));
7051 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7053 aopOp (result, ic, FALSE);
7055 /* if bitfield then unpack the bits */
7056 if (IS_BITVAR (retype))
7057 genUnpackBits (result, rname, PPOINTER);
7060 /* we have can just get the values */
7061 int size = AOP_SIZE (result);
7067 emitcode ("movx", "a,@%s", rname);
7068 aopPut (AOP (result), "a", offset);
7073 emitcode ("inc", "%s", rname);
7077 /* now some housekeeping stuff */
7078 if (aop) /* we had to allocate for this iCode */
7080 if (pi) aopPut ( AOP (left), rname, 0);
7081 freeAsmop (NULL, aop, ic, TRUE);
7085 /* we did not allocate which means left
7086 already in a pointer register, then
7087 if size > 0 && this could be used again
7088 we have to point it back to where it
7090 if ((AOP_SIZE (result) > 1 &&
7091 !OP_SYMBOL (left)->remat &&
7092 (OP_SYMBOL (left)->liveTo > ic->seq ||
7096 int size = AOP_SIZE (result) - 1;
7098 emitcode ("dec", "%s", rname);
7103 freeAsmop (left, NULL, ic, TRUE);
7104 freeAsmop (result, NULL, ic, TRUE);
7105 if (pi) pi->generated = 1;
7109 /*-----------------------------------------------------------------*/
7110 /* genFarPointerGet - gget value from far space */
7111 /*-----------------------------------------------------------------*/
7113 genFarPointerGet (operand * left,
7114 operand * result, iCode * ic, iCode * pi)
7117 sym_link *retype = getSpec (operandType (result));
7119 aopOp (left, ic, FALSE);
7121 /* if the operand is already in dptr
7122 then we do nothing else we move the value to dptr */
7123 if (AOP_TYPE (left) != AOP_STR)
7125 /* if this is remateriazable */
7126 if (AOP_TYPE (left) == AOP_IMMD)
7127 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7129 { /* we need to get it byte by byte */
7130 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7131 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7134 /* so dptr know contains the address */
7135 aopOp (result, ic, FALSE);
7137 /* if bit then unpack */
7138 if (IS_BITVAR (retype))
7139 genUnpackBits (result, "dptr", FPOINTER);
7142 size = AOP_SIZE (result);
7147 emitcode ("movx", "a,@dptr");
7148 aopPut (AOP (result), "a", offset++);
7150 emitcode ("inc", "dptr");
7154 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7155 aopPut ( AOP (left), "dpl", 0);
7156 aopPut ( AOP (left), "dph", 1);
7159 freeAsmop (left, NULL, ic, TRUE);
7160 freeAsmop (result, NULL, ic, TRUE);
7163 /*-----------------------------------------------------------------*/
7164 /* genCodePointerGet - gget value from code space */
7165 /*-----------------------------------------------------------------*/
7167 genCodePointerGet (operand * left,
7168 operand * result, iCode * ic, iCode *pi)
7171 sym_link *retype = getSpec (operandType (result));
7173 aopOp (left, ic, FALSE);
7175 /* if the operand is already in dptr
7176 then we do nothing else we move the value to dptr */
7177 if (AOP_TYPE (left) != AOP_STR)
7179 /* if this is remateriazable */
7180 if (AOP_TYPE (left) == AOP_IMMD)
7181 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7183 { /* we need to get it byte by byte */
7184 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7185 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7188 /* so dptr know contains the address */
7189 aopOp (result, ic, FALSE);
7191 /* if bit then unpack */
7192 if (IS_BITVAR (retype))
7193 genUnpackBits (result, "dptr", CPOINTER);
7196 size = AOP_SIZE (result);
7201 emitcode ("clr", "a");
7202 emitcode ("movc", "a,@a+dptr");
7203 aopPut (AOP (result), "a", offset++);
7205 emitcode ("inc", "dptr");
7209 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7210 aopPut ( AOP (left), "dpl", 0);
7211 aopPut ( AOP (left), "dph", 1);
7214 freeAsmop (left, NULL, ic, TRUE);
7215 freeAsmop (result, NULL, ic, TRUE);
7218 /*-----------------------------------------------------------------*/
7219 /* genGenPointerGet - gget value from generic pointer space */
7220 /*-----------------------------------------------------------------*/
7222 genGenPointerGet (operand * left,
7223 operand * result, iCode * ic, iCode *pi)
7226 sym_link *retype = getSpec (operandType (result));
7228 aopOp (left, ic, FALSE);
7230 /* if the operand is already in dptr
7231 then we do nothing else we move the value to dptr */
7232 if (AOP_TYPE (left) != AOP_STR)
7234 /* if this is remateriazable */
7235 if (AOP_TYPE (left) == AOP_IMMD)
7237 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7238 emitcode ("mov", "b,#%d", pointerCode (retype));
7241 { /* we need to get it byte by byte */
7242 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7243 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7244 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7247 /* so dptr know contains the address */
7248 aopOp (result, ic, FALSE);
7250 /* if bit then unpack */
7251 if (IS_BITVAR (retype))
7252 genUnpackBits (result, "dptr", GPOINTER);
7255 size = AOP_SIZE (result);
7260 emitcode ("lcall", "__gptrget");
7261 aopPut (AOP (result), "a", offset++);
7263 emitcode ("inc", "dptr");
7267 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7268 aopPut ( AOP (left), "dpl", 0);
7269 aopPut ( AOP (left), "dph", 1);
7272 freeAsmop (left, NULL, ic, TRUE);
7273 freeAsmop (result, NULL, ic, TRUE);
7276 /*-----------------------------------------------------------------*/
7277 /* genPointerGet - generate code for pointer get */
7278 /*-----------------------------------------------------------------*/
7280 genPointerGet (iCode * ic, iCode *pi)
7282 operand *left, *result;
7283 sym_link *type, *etype;
7286 left = IC_LEFT (ic);
7287 result = IC_RESULT (ic);
7289 /* depending on the type of pointer we need to
7290 move it to the correct pointer register */
7291 type = operandType (left);
7292 etype = getSpec (type);
7293 /* if left is of type of pointer then it is simple */
7294 if (IS_PTR (type) && !IS_FUNC (type->next))
7295 p_type = DCL_TYPE (type);
7298 /* we have to go by the storage class */
7299 p_type = PTR_TYPE (SPEC_OCLS (etype));
7302 /* now that we have the pointer type we assign
7303 the pointer values */
7309 genNearPointerGet (left, result, ic, pi);
7313 genPagedPointerGet (left, result, ic, pi);
7317 genFarPointerGet (left, result, ic, pi);
7321 genCodePointerGet (left, result, ic, pi);
7325 genGenPointerGet (left, result, ic, pi);
7331 /*-----------------------------------------------------------------*/
7332 /* genPackBits - generates code for packed bit storage */
7333 /*-----------------------------------------------------------------*/
7335 genPackBits (sym_link * etype,
7337 char *rname, int p_type)
7345 blen = SPEC_BLEN (etype);
7346 bstr = SPEC_BSTR (etype);
7348 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7351 /* if the bit lenth is less than or */
7352 /* it exactly fits a byte then */
7353 if (SPEC_BLEN (etype) <= 8)
7355 shCount = SPEC_BSTR (etype);
7357 /* shift left acc */
7360 if (SPEC_BLEN (etype) < 8)
7361 { /* if smaller than a byte */
7367 emitcode ("mov", "b,a");
7368 emitcode ("mov", "a,@%s", rname);
7372 emitcode ("mov", "b,a");
7373 emitcode ("movx", "a,@dptr");
7377 emitcode ("push", "b");
7378 emitcode ("push", "acc");
7379 emitcode ("lcall", "__gptrget");
7380 emitcode ("pop", "b");
7384 emitcode ("anl", "a,#0x%02x", (unsigned char)
7385 ((unsigned char) (0xFF << (blen + bstr)) |
7386 (unsigned char) (0xFF >> (8 - bstr))));
7387 emitcode ("orl", "a,b");
7388 if (p_type == GPOINTER)
7389 emitcode ("pop", "b");
7396 emitcode ("mov", "@%s,a", rname);
7400 emitcode ("movx", "@dptr,a");
7404 emitcode ("lcall", "__gptrput");
7409 if (SPEC_BLEN (etype) <= 8)
7412 emitcode ("inc", "%s", rname);
7413 rLen = SPEC_BLEN (etype);
7415 /* now generate for lengths greater than one byte */
7419 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7431 emitcode ("mov", "@%s,a", rname);
7434 emitcode ("mov", "@%s,%s", rname, l);
7439 emitcode ("movx", "@dptr,a");
7444 emitcode ("lcall", "__gptrput");
7447 emitcode ("inc", "%s", rname);
7452 /* last last was not complete */
7455 /* save the byte & read byte */
7459 emitcode ("mov", "b,a");
7460 emitcode ("mov", "a,@%s", rname);
7464 emitcode ("mov", "b,a");
7465 emitcode ("movx", "a,@dptr");
7469 emitcode ("push", "b");
7470 emitcode ("push", "acc");
7471 emitcode ("lcall", "__gptrget");
7472 emitcode ("pop", "b");
7476 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7477 emitcode ("orl", "a,b");
7480 if (p_type == GPOINTER)
7481 emitcode ("pop", "b");
7487 emitcode ("mov", "@%s,a", rname);
7491 emitcode ("movx", "@dptr,a");
7495 emitcode ("lcall", "__gptrput");
7499 /*-----------------------------------------------------------------*/
7500 /* genDataPointerSet - remat pointer to data space */
7501 /*-----------------------------------------------------------------*/
7503 genDataPointerSet (operand * right,
7507 int size, offset = 0;
7508 char *l, buffer[256];
7510 aopOp (right, ic, FALSE);
7512 l = aopGet (AOP (result), 0, FALSE, TRUE);
7513 size = AOP_SIZE (right);
7517 sprintf (buffer, "(%s + %d)", l + 1, offset);
7519 sprintf (buffer, "%s", l + 1);
7520 emitcode ("mov", "%s,%s", buffer,
7521 aopGet (AOP (right), offset++, FALSE, FALSE));
7524 freeAsmop (right, NULL, ic, TRUE);
7525 freeAsmop (result, NULL, ic, TRUE);
7528 /*-----------------------------------------------------------------*/
7529 /* genNearPointerSet - emitcode for near pointer put */
7530 /*-----------------------------------------------------------------*/
7532 genNearPointerSet (operand * right,
7540 sym_link *retype, *letype;
7541 sym_link *ptype = operandType (result);
7543 retype = getSpec (operandType (right));
7544 letype = getSpec (ptype);
7545 aopOp (result, ic, FALSE);
7547 /* if the result is rematerializable &
7548 in data space & not a bit variable */
7549 if (AOP_TYPE (result) == AOP_IMMD &&
7550 DCL_TYPE (ptype) == POINTER &&
7551 !IS_BITVAR (retype) &&
7552 !IS_BITVAR (letype))
7554 genDataPointerSet (right, result, ic);
7558 /* if the value is already in a pointer register
7559 then don't need anything more */
7560 if (!AOP_INPREG (AOP (result)))
7562 /* otherwise get a free pointer register */
7564 preg = getFreePtr (ic, &aop, FALSE);
7565 emitcode ("mov", "%s,%s",
7567 aopGet (AOP (result), 0, FALSE, TRUE));
7571 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7573 aopOp (right, ic, FALSE);
7575 /* if bitfield then unpack the bits */
7576 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7577 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7580 /* we have can just get the values */
7581 int size = AOP_SIZE (right);
7586 l = aopGet (AOP (right), offset, FALSE, TRUE);
7590 emitcode ("mov", "@%s,a", rname);
7593 emitcode ("mov", "@%s,%s", rname, l);
7595 emitcode ("inc", "%s", rname);
7600 /* now some housekeeping stuff */
7601 if (aop) /* we had to allocate for this iCode */
7603 if (pi) aopPut (AOP (result),rname,0);
7604 freeAsmop (NULL, aop, ic, TRUE);
7608 /* we did not allocate which means left
7609 already in a pointer register, then
7610 if size > 0 && this could be used again
7611 we have to point it back to where it
7613 if ((AOP_SIZE (right) > 1 &&
7614 !OP_SYMBOL (result)->remat &&
7615 (OP_SYMBOL (result)->liveTo > ic->seq ||
7619 int size = AOP_SIZE (right) - 1;
7621 emitcode ("dec", "%s", rname);
7626 if (pi) pi->generated = 1;
7627 freeAsmop (result, NULL, ic, TRUE);
7628 freeAsmop (right, NULL, ic, TRUE);
7631 /*-----------------------------------------------------------------*/
7632 /* genPagedPointerSet - emitcode for Paged pointer put */
7633 /*-----------------------------------------------------------------*/
7635 genPagedPointerSet (operand * right,
7643 sym_link *retype, *letype;
7645 retype = getSpec (operandType (right));
7646 letype = getSpec (operandType (result));
7648 aopOp (result, ic, FALSE);
7650 /* if the value is already in a pointer register
7651 then don't need anything more */
7652 if (!AOP_INPREG (AOP (result)))
7654 /* otherwise get a free pointer register */
7656 preg = getFreePtr (ic, &aop, FALSE);
7657 emitcode ("mov", "%s,%s",
7659 aopGet (AOP (result), 0, FALSE, TRUE));
7663 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7665 aopOp (right, ic, FALSE);
7667 /* if bitfield then unpack the bits */
7668 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7669 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7672 /* we have can just get the values */
7673 int size = AOP_SIZE (right);
7678 l = aopGet (AOP (right), offset, FALSE, TRUE);
7681 emitcode ("movx", "@%s,a", rname);
7684 emitcode ("inc", "%s", rname);
7690 /* now some housekeeping stuff */
7691 if (aop) /* we had to allocate for this iCode */
7693 if (pi) aopPut (AOP (result),rname,0);
7694 freeAsmop (NULL, aop, ic, TRUE);
7698 /* we did not allocate which means left
7699 already in a pointer register, then
7700 if size > 0 && this could be used again
7701 we have to point it back to where it
7703 if (AOP_SIZE (right) > 1 &&
7704 !OP_SYMBOL (result)->remat &&
7705 (OP_SYMBOL (result)->liveTo > ic->seq ||
7708 int size = AOP_SIZE (right) - 1;
7710 emitcode ("dec", "%s", rname);
7715 if (pi) pi->generated = 1;
7716 freeAsmop (result, NULL, ic, TRUE);
7717 freeAsmop (right, NULL, ic, TRUE);
7722 /*-----------------------------------------------------------------*/
7723 /* genFarPointerSet - set value from far space */
7724 /*-----------------------------------------------------------------*/
7726 genFarPointerSet (operand * right,
7727 operand * result, iCode * ic, iCode * pi)
7730 sym_link *retype = getSpec (operandType (right));
7731 sym_link *letype = getSpec (operandType (result));
7732 aopOp (result, ic, FALSE);
7734 /* if the operand is already in dptr
7735 then we do nothing else we move the value to dptr */
7736 if (AOP_TYPE (result) != AOP_STR)
7738 /* if this is remateriazable */
7739 if (AOP_TYPE (result) == AOP_IMMD)
7740 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7742 { /* we need to get it byte by byte */
7743 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7744 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7747 /* so dptr know contains the address */
7748 aopOp (right, ic, FALSE);
7750 /* if bit then unpack */
7751 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7752 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7755 size = AOP_SIZE (right);
7760 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7762 emitcode ("movx", "@dptr,a");
7764 emitcode ("inc", "dptr");
7767 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7768 aopPut (AOP(result),"dpl",0);
7769 aopPut (AOP(result),"dph",1);
7772 freeAsmop (result, NULL, ic, TRUE);
7773 freeAsmop (right, NULL, ic, TRUE);
7776 /*-----------------------------------------------------------------*/
7777 /* genGenPointerSet - set value from generic pointer space */
7778 /*-----------------------------------------------------------------*/
7780 genGenPointerSet (operand * right,
7781 operand * result, iCode * ic, iCode * pi)
7784 sym_link *retype = getSpec (operandType (right));
7785 sym_link *letype = getSpec (operandType (result));
7787 aopOp (result, ic, FALSE);
7789 /* if the operand is already in dptr
7790 then we do nothing else we move the value to dptr */
7791 if (AOP_TYPE (result) != AOP_STR)
7793 /* if this is remateriazable */
7794 if (AOP_TYPE (result) == AOP_IMMD)
7796 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7797 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7800 { /* we need to get it byte by byte */
7801 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7802 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7803 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7806 /* so dptr know contains the address */
7807 aopOp (right, ic, FALSE);
7809 /* if bit then unpack */
7810 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7811 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7814 size = AOP_SIZE (right);
7819 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7821 emitcode ("lcall", "__gptrput");
7823 emitcode ("inc", "dptr");
7827 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7828 aopPut (AOP(result),"dpl",0);
7829 aopPut (AOP(result),"dph",1);
7832 freeAsmop (result, NULL, ic, TRUE);
7833 freeAsmop (right, NULL, ic, TRUE);
7836 /*-----------------------------------------------------------------*/
7837 /* genPointerSet - stores the value into a pointer location */
7838 /*-----------------------------------------------------------------*/
7840 genPointerSet (iCode * ic, iCode *pi)
7842 operand *right, *result;
7843 sym_link *type, *etype;
7846 right = IC_RIGHT (ic);
7847 result = IC_RESULT (ic);
7849 /* depending on the type of pointer we need to
7850 move it to the correct pointer register */
7851 type = operandType (result);
7852 etype = getSpec (type);
7853 /* if left is of type of pointer then it is simple */
7854 if (IS_PTR (type) && !IS_FUNC (type->next))
7856 p_type = DCL_TYPE (type);
7860 /* we have to go by the storage class */
7861 p_type = PTR_TYPE (SPEC_OCLS (etype));
7864 /* now that we have the pointer type we assign
7865 the pointer values */
7871 genNearPointerSet (right, result, ic, pi);
7875 genPagedPointerSet (right, result, ic, pi);
7879 genFarPointerSet (right, result, ic, pi);
7883 genGenPointerSet (right, result, ic, pi);
7889 /*-----------------------------------------------------------------*/
7890 /* genIfx - generate code for Ifx statement */
7891 /*-----------------------------------------------------------------*/
7893 genIfx (iCode * ic, iCode * popIc)
7895 operand *cond = IC_COND (ic);
7898 aopOp (cond, ic, FALSE);
7900 /* get the value into acc */
7901 if (AOP_TYPE (cond) != AOP_CRY)
7905 /* the result is now in the accumulator */
7906 freeAsmop (cond, NULL, ic, TRUE);
7908 /* if there was something to be popped then do it */
7912 /* if the condition is a bit variable */
7913 if (isbit && IS_ITEMP (cond) &&
7915 genIfxJump (ic, SPIL_LOC (cond)->rname);
7916 else if (isbit && !IS_ITEMP (cond))
7917 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7919 genIfxJump (ic, "a");
7924 /*-----------------------------------------------------------------*/
7925 /* genAddrOf - generates code for address of */
7926 /*-----------------------------------------------------------------*/
7928 genAddrOf (iCode * ic)
7930 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7933 aopOp (IC_RESULT (ic), ic, FALSE);
7935 /* if the operand is on the stack then we
7936 need to get the stack offset of this
7940 /* if it has an offset then we need to compute
7944 emitcode ("mov", "a,_bp");
7945 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7946 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7950 /* we can just move _bp */
7951 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7953 /* fill the result with zero */
7954 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7959 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7965 /* object not on stack then we need the name */
7966 size = AOP_SIZE (IC_RESULT (ic));
7971 char s[SDCC_NAME_MAX];
7973 sprintf (s, "#(%s >> %d)",
7977 sprintf (s, "#%s", sym->rname);
7978 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7982 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7986 /*-----------------------------------------------------------------*/
7987 /* genFarFarAssign - assignment when both are in far space */
7988 /*-----------------------------------------------------------------*/
7990 genFarFarAssign (operand * result, operand * right, iCode * ic)
7992 int size = AOP_SIZE (right);
7995 /* first push the right side on to the stack */
7998 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8000 emitcode ("push", "acc");
8003 freeAsmop (right, NULL, ic, FALSE);
8004 /* now assign DPTR to result */
8005 aopOp (result, ic, FALSE);
8006 size = AOP_SIZE (result);
8009 emitcode ("pop", "acc");
8010 aopPut (AOP (result), "a", --offset);
8012 freeAsmop (result, NULL, ic, FALSE);
8016 /*-----------------------------------------------------------------*/
8017 /* genAssign - generate code for assignment */
8018 /*-----------------------------------------------------------------*/
8020 genAssign (iCode * ic)
8022 operand *result, *right;
8024 unsigned long lit = 0L;
8026 D(emitcode(";","genAssign"));
8028 result = IC_RESULT (ic);
8029 right = IC_RIGHT (ic);
8031 /* if they are the same */
8032 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8035 aopOp (right, ic, FALSE);
8037 /* special case both in far space */
8038 if (AOP_TYPE (right) == AOP_DPTR &&
8039 IS_TRUE_SYMOP (result) &&
8040 isOperandInFarSpace (result))
8043 genFarFarAssign (result, right, ic);
8047 aopOp (result, ic, TRUE);
8049 /* if they are the same registers */
8050 if (sameRegs (AOP (right), AOP (result)))
8053 /* if the result is a bit */
8054 if (AOP_TYPE (result) == AOP_CRY)
8057 /* if the right size is a literal then
8058 we know what the value is */
8059 if (AOP_TYPE (right) == AOP_LIT)
8061 if (((int) operandLitValue (right)))
8062 aopPut (AOP (result), one, 0);
8064 aopPut (AOP (result), zero, 0);
8068 /* the right is also a bit variable */
8069 if (AOP_TYPE (right) == AOP_CRY)
8071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8072 aopPut (AOP (result), "c", 0);
8078 aopPut (AOP (result), "a", 0);
8082 /* bit variables done */
8084 size = AOP_SIZE (result);
8086 if (AOP_TYPE (right) == AOP_LIT)
8087 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8089 (AOP_TYPE (result) != AOP_REG) &&
8090 (AOP_TYPE (right) == AOP_LIT) &&
8091 !IS_FLOAT (operandType (right)) &&
8094 emitcode ("clr", "a");
8097 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8098 aopPut (AOP (result), "a", size);
8100 aopPut (AOP (result),
8101 aopGet (AOP (right), size, FALSE, FALSE),
8109 aopPut (AOP (result),
8110 aopGet (AOP (right), offset, FALSE, FALSE),
8117 freeAsmop (right, NULL, ic, TRUE);
8118 freeAsmop (result, NULL, ic, TRUE);
8121 /*-----------------------------------------------------------------*/
8122 /* genJumpTab - genrates code for jump table */
8123 /*-----------------------------------------------------------------*/
8125 genJumpTab (iCode * ic)
8130 aopOp (IC_JTCOND (ic), ic, FALSE);
8131 /* get the condition into accumulator */
8132 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8134 /* multiply by three */
8135 emitcode ("add", "a,acc");
8136 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8137 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8139 jtab = newiTempLabel (NULL);
8140 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8141 emitcode ("jmp", "@a+dptr");
8142 emitcode ("", "%05d$:", jtab->key + 100);
8143 /* now generate the jump labels */
8144 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8145 jtab = setNextItem (IC_JTLABELS (ic)))
8146 emitcode ("ljmp", "%05d$", jtab->key + 100);
8150 /*-----------------------------------------------------------------*/
8151 /* genCast - gen code for casting */
8152 /*-----------------------------------------------------------------*/
8154 genCast (iCode * ic)
8156 operand *result = IC_RESULT (ic);
8157 sym_link *ctype = operandType (IC_LEFT (ic));
8158 sym_link *rtype = operandType (IC_RIGHT (ic));
8159 operand *right = IC_RIGHT (ic);
8162 D(emitcode(";", "genCast"));
8164 /* if they are equivalent then do nothing */
8165 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8168 aopOp (right, ic, FALSE);
8169 aopOp (result, ic, FALSE);
8171 /* if the result is a bit */
8172 if (AOP_TYPE (result) == AOP_CRY)
8174 /* if the right size is a literal then
8175 we know what the value is */
8176 if (AOP_TYPE (right) == AOP_LIT)
8178 if (((int) operandLitValue (right)))
8179 aopPut (AOP (result), one, 0);
8181 aopPut (AOP (result), zero, 0);
8186 /* the right is also a bit variable */
8187 if (AOP_TYPE (right) == AOP_CRY)
8189 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8190 aopPut (AOP (result), "c", 0);
8196 aopPut (AOP (result), "a", 0);
8200 /* if they are the same size : or less */
8201 if (AOP_SIZE (result) <= AOP_SIZE (right))
8204 /* if they are in the same place */
8205 if (sameRegs (AOP (right), AOP (result)))
8208 /* if they in different places then copy */
8209 size = AOP_SIZE (result);
8213 aopPut (AOP (result),
8214 aopGet (AOP (right), offset, FALSE, FALSE),
8222 /* if the result is of type pointer */
8227 sym_link *type = operandType (right);
8228 sym_link *etype = getSpec (type);
8230 /* pointer to generic pointer */
8231 if (IS_GENPTR (ctype))
8236 p_type = DCL_TYPE (type);
8239 if (SPEC_SCLS(etype)==S_REGISTER) {
8240 // let's assume it is a generic pointer
8243 /* we have to go by the storage class */
8244 p_type = PTR_TYPE (SPEC_OCLS (etype));
8248 /* the first two bytes are known */
8249 size = GPTRSIZE - 1;
8253 aopPut (AOP (result),
8254 aopGet (AOP (right), offset, FALSE, FALSE),
8258 /* the last byte depending on type */
8274 case PPOINTER: // what the fck is this?
8279 /* this should never happen */
8280 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8281 "got unknown pointer type");
8284 aopPut (AOP (result), l, GPTRSIZE - 1);
8288 /* just copy the pointers */
8289 size = AOP_SIZE (result);
8293 aopPut (AOP (result),
8294 aopGet (AOP (right), offset, FALSE, FALSE),
8301 /* so we now know that the size of destination is greater
8302 than the size of the source */
8303 /* we move to result for the size of source */
8304 size = AOP_SIZE (right);
8308 aopPut (AOP (result),
8309 aopGet (AOP (right), offset, FALSE, FALSE),
8314 /* now depending on the sign of the source && destination */
8315 size = AOP_SIZE (result) - AOP_SIZE (right);
8316 /* if unsigned or not an integral type */
8317 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8320 aopPut (AOP (result), zero, offset++);
8324 /* we need to extend the sign :{ */
8325 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8328 emitcode ("rlc", "a");
8329 emitcode ("subb", "a,acc");
8331 aopPut (AOP (result), "a", offset++);
8334 /* we are done hurray !!!! */
8337 freeAsmop (right, NULL, ic, TRUE);
8338 freeAsmop (result, NULL, ic, TRUE);
8342 /*-----------------------------------------------------------------*/
8343 /* genDjnz - generate decrement & jump if not zero instrucion */
8344 /*-----------------------------------------------------------------*/
8346 genDjnz (iCode * ic, iCode * ifx)
8352 /* if the if condition has a false label
8353 then we cannot save */
8357 /* if the minus is not of the form
8359 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8360 !IS_OP_LITERAL (IC_RIGHT (ic)))
8363 if (operandLitValue (IC_RIGHT (ic)) != 1)
8366 /* if the size of this greater than one then no
8368 if (getSize (operandType (IC_RESULT (ic))) > 1)
8371 /* otherwise we can save BIG */
8372 lbl = newiTempLabel (NULL);
8373 lbl1 = newiTempLabel (NULL);
8375 aopOp (IC_RESULT (ic), ic, FALSE);
8377 if (AOP_NEEDSACC(IC_RESULT(ic)))
8379 /* If the result is accessed indirectly via
8380 * the accumulator, we must explicitly write
8381 * it back after the decrement.
8383 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8385 if (strcmp(rByte, "a"))
8387 /* Something is hopelessly wrong */
8388 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8389 __FILE__, __LINE__);
8390 /* We can just give up; the generated code will be inefficient,
8393 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8396 emitcode ("dec", "%s", rByte);
8397 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8398 emitcode ("jnz", "%05d$", lbl->key + 100);
8400 else if (IS_AOP_PREG (IC_RESULT (ic)))
8402 emitcode ("dec", "%s",
8403 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8404 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8405 emitcode ("jnz", "%05d$", lbl->key + 100);
8409 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8412 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8413 emitcode ("", "%05d$:", lbl->key + 100);
8414 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8415 emitcode ("", "%05d$:", lbl1->key + 100);
8417 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8422 /*-----------------------------------------------------------------*/
8423 /* genReceive - generate code for a receive iCode */
8424 /*-----------------------------------------------------------------*/
8426 genReceive (iCode * ic)
8428 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8429 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8430 IS_TRUE_SYMOP (IC_RESULT (ic))))
8433 int size = getSize (operandType (IC_RESULT (ic)));
8434 int offset = fReturnSizeMCS51 - size;
8437 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8438 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8441 aopOp (IC_RESULT (ic), ic, FALSE);
8442 size = AOP_SIZE (IC_RESULT (ic));
8446 emitcode ("pop", "acc");
8447 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8454 aopOp (IC_RESULT (ic), ic, FALSE);
8456 assignResultValue (IC_RESULT (ic));
8459 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8462 /*-----------------------------------------------------------------*/
8463 /* gen51Code - generate code for 8051 based controllers */
8464 /*-----------------------------------------------------------------*/
8466 gen51Code (iCode * lic)
8471 lineHead = lineCurr = NULL;
8473 /* print the allocation information */
8475 printAllocInfo (currFunc, codeOutFile);
8476 /* if debug information required */
8477 /* if (options.debug && currFunc) { */
8478 if (options.debug && currFunc)
8480 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8482 if (IS_STATIC (currFunc->etype))
8483 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8485 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8488 /* stack pointer name */
8489 if (options.useXstack)
8495 for (ic = lic; ic; ic = ic->next)
8498 if (cln != ic->lineno)
8503 emitcode ("", "C$%s$%d$%d$%d ==.",
8504 FileBaseName (ic->filename), ic->lineno,
8505 ic->level, ic->block);
8508 emitcode (";", "%s %d", ic->filename, ic->lineno);
8511 /* if the result is marked as
8512 spilt and rematerializable or code for
8513 this has already been generated then
8515 if (resultRemat (ic) || ic->generated)
8518 /* depending on the operation */
8538 /* IPOP happens only when trying to restore a
8539 spilt live range, if there is an ifx statement
8540 following this pop then the if statement might
8541 be using some of the registers being popped which
8542 would destory the contents of the register so
8543 we need to check for this condition and handle it */
8545 ic->next->op == IFX &&
8546 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8547 genIfx (ic->next, ic);
8565 genEndFunction (ic);
8585 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8602 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8606 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8613 /* note these two are xlated by algebraic equivalence
8614 during parsing SDCC.y */
8615 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8616 "got '>=' or '<=' shouldn't have come here");
8620 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8632 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8636 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8640 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8667 case GET_VALUE_AT_ADDRESS:
8668 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8672 if (POINTER_SET (ic))
8673 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8699 addSet (&_G.sendSet, ic);
8708 /* now we are ready to call the
8709 peep hole optimizer */
8710 if (!options.nopeep)
8711 peepHole (&lineHead);
8713 /* now do the actual printing */
8714 printLine (lineHead, codeOutFile);