1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #include "SDCCpeeph.h"
59 char *aopLiteral (value * val, int offset);
62 /* this is the down and dirty file with all kinds of
63 kludgy & hacky stuff. This is what it is all about
64 CODE GENERATION for a specific MCU . some of the
65 routines may be reusable, will have to see */
67 static char *zero = "#0x00";
68 static char *one = "#0x01";
72 {"dpl", "dph", "b", "a"};
73 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
74 char **fReturn = fReturn8051;
75 static char *accUse[] =
78 static short rbank = -1;
92 extern int mcs51_ptrRegReq;
93 extern int mcs51_nRegs;
94 extern FILE *codeOutFile;
95 static void saveRBank (int, iCode *, bool);
96 #define RESULTONSTACK(x) \
97 (IC_RESULT(x) && IC_RESULT(x)->aop && \
98 IC_RESULT(x)->aop->type == AOP_STK )
100 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] =
108 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] =
111 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
112 0x07, 0x03, 0x01, 0x00};
119 /*-----------------------------------------------------------------*/
120 /* emitcode - writes the code into a file : for now it is simple */
121 /*-----------------------------------------------------------------*/
123 emitcode (char *inst, char *fmt,...)
126 char lb[INITIAL_INLINEASM];
134 sprintf (lb, "%s\t", inst);
136 sprintf (lb, "%s", inst);
137 vsprintf (lb + (strlen (lb)), fmt, ap);
140 vsprintf (lb, fmt, ap);
142 while (isspace (*lbp))
146 lineCurr = (lineCurr ?
147 connectLine (lineCurr, newLineNode (lb)) :
148 (lineHead = newLineNode (lb)));
149 lineCurr->isInline = _G.inLine;
150 lineCurr->isDebug = _G.debugLine;
154 /*-----------------------------------------------------------------*/
155 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
156 /*-----------------------------------------------------------------*/
158 getFreePtr (iCode * ic, asmop ** aopp, bool result)
160 bool r0iu = FALSE, r1iu = FALSE;
161 bool r0ou = FALSE, r1ou = FALSE;
163 /* the logic: if r0 & r1 used in the instruction
164 then we are in trouble otherwise */
166 /* first check if r0 & r1 are used by this
167 instruction, in which case we are in trouble */
168 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
169 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
174 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
175 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
177 /* if no usage of r0 then return it */
180 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
181 (*aopp)->type = AOP_R0;
183 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
186 /* if no usage of r1 then return it */
189 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
190 (*aopp)->type = AOP_R1;
192 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
195 /* now we know they both have usage */
196 /* if r0 not used in this instruction */
199 /* push it if not already pushed */
202 emitcode ("push", "%s",
203 mcs51_regWithIdx (R0_IDX)->dname);
207 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
208 (*aopp)->type = AOP_R0;
210 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
213 /* if r1 not used then */
217 /* push it if not already pushed */
220 emitcode ("push", "%s",
221 mcs51_regWithIdx (R1_IDX)->dname);
225 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
226 (*aopp)->type = AOP_R1;
227 return mcs51_regWithIdx (R1_IDX);
231 /* I said end of world but not quite end of world yet */
232 /* if this is a result then we can push it on the stack */
235 (*aopp)->type = AOP_STK;
239 /* other wise this is true end of the world */
240 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
241 "getFreePtr should never reach here");
245 /*-----------------------------------------------------------------*/
246 /* newAsmop - creates a new asmOp */
247 /*-----------------------------------------------------------------*/
249 newAsmop (short type)
253 aop = Safe_calloc (1, sizeof (asmop));
258 /*-----------------------------------------------------------------*/
259 /* pointerCode - returns the code for a pointer type */
260 /*-----------------------------------------------------------------*/
262 pointerCode (sym_link * etype)
265 return PTR_TYPE (SPEC_OCLS (etype));
269 /*-----------------------------------------------------------------*/
270 /* aopForSym - for a true symbol */
271 /*-----------------------------------------------------------------*/
273 aopForSym (iCode * ic, symbol * sym, bool result)
278 wassertl (ic != NULL, "Got a null iCode");
279 wassertl (sym != NULL, "Got a null symbol");
281 space = SPEC_OCLS (sym->etype);
283 /* if already has one */
287 /* assign depending on the storage class */
288 /* if it is on the stack or indirectly addressable */
289 /* space we need to assign either r0 or r1 to it */
290 if (sym->onStack || sym->iaccess)
292 sym->aop = aop = newAsmop (0);
293 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
294 aop->size = getSize (sym->type);
296 /* now assign the address of the variable to
297 the pointer register */
298 if (aop->type != AOP_STK)
304 emitcode ("push", "acc");
306 emitcode ("mov", "a,_bp");
307 emitcode ("add", "a,#0x%02x",
309 ((char) (sym->stack - _G.nRegsSaved)) :
310 ((char) sym->stack)) & 0xff);
311 emitcode ("mov", "%s,a",
312 aop->aopu.aop_ptr->name);
315 emitcode ("pop", "acc");
318 emitcode ("mov", "%s,#%s",
319 aop->aopu.aop_ptr->name,
321 aop->paged = space->paged;
324 aop->aopu.aop_stk = sym->stack;
328 /* if in bit space */
329 if (IN_BITSPACE (space))
331 sym->aop = aop = newAsmop (AOP_CRY);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
336 /* if it is in direct space */
337 if (IN_DIRSPACE (space))
339 sym->aop = aop = newAsmop (AOP_DIR);
340 aop->aopu.aop_dir = sym->rname;
341 aop->size = getSize (sym->type);
345 /* special case for a function */
346 if (IS_FUNC (sym->type))
348 sym->aop = aop = newAsmop (AOP_IMMD);
349 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
350 strcpy (aop->aopu.aop_immd, sym->rname);
351 aop->size = FPTRSIZE;
355 /* only remaining is far space */
356 /* in which case DPTR gets the address */
357 sym->aop = aop = newAsmop (AOP_DPTR);
358 emitcode ("mov", "dptr,#%s", sym->rname);
359 aop->size = getSize (sym->type);
361 /* if it is in code space */
362 if (IN_CODESPACE (space))
368 /*-----------------------------------------------------------------*/
369 /* aopForRemat - rematerialzes an object */
370 /*-----------------------------------------------------------------*/
372 aopForRemat (symbol * sym)
374 iCode *ic = sym->rematiCode;
375 asmop *aop = newAsmop (AOP_IMMD);
381 val += (int) operandLitValue (IC_RIGHT (ic));
382 else if (ic->op == '-')
383 val -= (int) operandLitValue (IC_RIGHT (ic));
387 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
391 sprintf (buffer, "(%s %c 0x%04x)",
392 OP_SYMBOL (IC_LEFT (ic))->rname,
393 val >= 0 ? '+' : '-',
396 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
398 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
399 strcpy (aop->aopu.aop_immd, buffer);
403 /*-----------------------------------------------------------------*/
404 /* regsInCommon - two operands have some registers in common */
405 /*-----------------------------------------------------------------*/
407 regsInCommon (operand * op1, operand * op2)
412 /* if they have registers in common */
413 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
416 sym1 = OP_SYMBOL (op1);
417 sym2 = OP_SYMBOL (op2);
419 if (sym1->nRegs == 0 || sym2->nRegs == 0)
422 for (i = 0; i < sym1->nRegs; i++)
428 for (j = 0; j < sym2->nRegs; j++)
433 if (sym2->regs[j] == sym1->regs[i])
441 /*-----------------------------------------------------------------*/
442 /* operandsEqu - equivalent */
443 /*-----------------------------------------------------------------*/
445 operandsEqu (operand * op1, operand * op2)
449 /* if they not symbols */
450 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
453 sym1 = OP_SYMBOL (op1);
454 sym2 = OP_SYMBOL (op2);
456 /* if both are itemps & one is spilt
457 and the other is not then false */
458 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
459 sym1->isspilt != sym2->isspilt)
462 /* if they are the same */
466 if (strcmp (sym1->rname, sym2->rname) == 0)
470 /* if left is a tmp & right is not */
471 if (IS_ITEMP (op1) &&
474 (sym1->usl.spillLoc == sym2))
477 if (IS_ITEMP (op2) &&
481 (sym2->usl.spillLoc == sym1))
487 /*-----------------------------------------------------------------*/
488 /* sameRegs - two asmops have the same registers */
489 /*-----------------------------------------------------------------*/
491 sameRegs (asmop * aop1, asmop * aop2)
498 if (aop1->type != AOP_REG ||
499 aop2->type != AOP_REG)
502 if (aop1->size != aop2->size)
505 for (i = 0; i < aop1->size; i++)
506 if (aop1->aopu.aop_reg[i] !=
507 aop2->aopu.aop_reg[i])
513 /*-----------------------------------------------------------------*/
514 /* aopOp - allocates an asmop for an operand : */
515 /*-----------------------------------------------------------------*/
517 aopOp (operand * op, iCode * ic, bool result)
526 /* if this a literal */
527 if (IS_OP_LITERAL (op))
529 op->aop = aop = newAsmop (AOP_LIT);
530 aop->aopu.aop_lit = op->operand.valOperand;
531 aop->size = getSize (operandType (op));
535 /* if already has a asmop then continue */
539 /* if the underlying symbol has a aop */
540 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
542 op->aop = OP_SYMBOL (op)->aop;
546 /* if this is a true symbol */
547 if (IS_TRUE_SYMOP (op))
549 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
553 /* this is a temporary : this has
559 e) can be a return use only */
561 sym = OP_SYMBOL (op);
564 /* if the type is a conditional */
565 if (sym->regType == REG_CND)
567 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
572 /* if it is spilt then two situations
574 b) has a spill location */
575 if (sym->isspilt || sym->nRegs == 0)
578 /* rematerialize it NOW */
581 sym->aop = op->aop = aop =
583 aop->size = getSize (sym->type);
590 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
591 aop->size = getSize (sym->type);
592 for (i = 0; i < 2; i++)
593 aop->aopu.aop_str[i] = accUse[i];
600 aop = op->aop = sym->aop = newAsmop (AOP_STR);
601 aop->size = getSize (sym->type);
602 for (i = 0; i < fReturnSizeMCS51; i++)
603 aop->aopu.aop_str[i] = fReturn[i];
607 /* else spill location */
608 sym->aop = op->aop = aop =
609 aopForSym (ic, sym->usl.spillLoc, result);
610 aop->size = getSize (sym->type);
614 /* must be in a register */
615 sym->aop = op->aop = aop = newAsmop (AOP_REG);
616 aop->size = sym->nRegs;
617 for (i = 0; i < sym->nRegs; i++)
618 aop->aopu.aop_reg[i] = sym->regs[i];
621 /*-----------------------------------------------------------------*/
622 /* freeAsmop - free up the asmop given to an operand */
623 /*----------------------------------------------------------------*/
625 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
642 /* depending on the asmop type only three cases need work AOP_RO
643 , AOP_R1 && AOP_STK */
651 emitcode ("pop", "ar0");
655 bitVectUnSetBit (ic->rUsed, R0_IDX);
663 emitcode ("pop", "ar1");
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
673 int stk = aop->aopu.aop_stk + aop->size;
674 bitVectUnSetBit (ic->rUsed, R0_IDX);
675 bitVectUnSetBit (ic->rUsed, R1_IDX);
677 getFreePtr (ic, &aop, FALSE);
681 emitcode ("mov", "a,_bp");
682 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
683 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
687 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
692 emitcode ("pop", "acc");
693 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
696 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
699 freeAsmop (op, NULL, ic, TRUE);
702 emitcode ("pop", "ar0");
708 emitcode ("pop", "ar1");
715 /* all other cases just dealloc */
721 OP_SYMBOL (op)->aop = NULL;
722 /* if the symbol has a spill */
724 SPIL_LOC (op)->aop = NULL;
729 /*-----------------------------------------------------------------*/
730 /* aopGet - for fetching value of the aop */
731 /*-----------------------------------------------------------------*/
733 aopGet (asmop * aop, int offset, bool bit16, bool dname)
738 /* offset is greater than
740 if (offset > (aop->size - 1) &&
741 aop->type != AOP_LIT)
744 /* depending on type */
750 /* if we need to increment it */
751 while (offset > aop->coff)
753 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
757 while (offset < aop->coff)
759 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
766 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
767 return (dname ? "acc" : "a");
769 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
770 rs = Safe_calloc (1, strlen (s) + 1);
775 while (offset > aop->coff)
777 emitcode ("inc", "dptr");
781 while (offset < aop->coff)
783 emitcode ("lcall", "__decdptr");
790 emitcode ("clr", "a");
791 emitcode ("movc", "a,@a+dptr");
795 emitcode ("movx", "a,@dptr");
797 return (dname ? "acc" : "a");
802 sprintf (s, "#%s", aop->aopu.aop_immd);
804 sprintf (s, "#(%s >> %d)",
810 rs = Safe_calloc (1, strlen (s) + 1);
816 sprintf (s, "(%s + %d)",
820 sprintf (s, "%s", aop->aopu.aop_dir);
821 rs = Safe_calloc (1, strlen (s) + 1);
827 return aop->aopu.aop_reg[offset]->dname;
829 return aop->aopu.aop_reg[offset]->name;
832 emitcode ("clr", "a");
833 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
834 emitcode ("rlc", "a");
835 return (dname ? "acc" : "a");
838 if (!offset && dname)
840 return aop->aopu.aop_str[offset];
843 return aopLiteral (aop->aopu.aop_lit, offset);
847 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
851 return aop->aopu.aop_str[offset];
855 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
856 "aopget got unsupported aop->type");
859 /*-----------------------------------------------------------------*/
860 /* aopPut - puts a string for a aop */
861 /*-----------------------------------------------------------------*/
863 aopPut (asmop * aop, char *s, int offset)
867 if (aop->size && offset > (aop->size - 1))
869 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
870 "aopPut got offset > aop->size");
874 /* will assign value to value */
875 /* depending on where it is ofcourse */
880 sprintf (d, "(%s + %d)",
881 aop->aopu.aop_dir, offset);
883 sprintf (d, "%s", aop->aopu.aop_dir);
886 emitcode ("mov", "%s,%s", d, s);
891 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
892 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
895 strcmp (s, "r0") == 0 ||
896 strcmp (s, "r1") == 0 ||
897 strcmp (s, "r2") == 0 ||
898 strcmp (s, "r3") == 0 ||
899 strcmp (s, "r4") == 0 ||
900 strcmp (s, "r5") == 0 ||
901 strcmp (s, "r6") == 0 ||
902 strcmp (s, "r7") == 0)
903 emitcode ("mov", "%s,%s",
904 aop->aopu.aop_reg[offset]->dname, s);
906 emitcode ("mov", "%s,%s",
907 aop->aopu.aop_reg[offset]->name, s);
914 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
915 "aopPut writting to code space");
919 while (offset > aop->coff)
922 emitcode ("inc", "dptr");
925 while (offset < aop->coff)
928 emitcode ("lcall", "__decdptr");
933 /* if not in accumulater */
936 emitcode ("movx", "@dptr,a");
941 while (offset > aop->coff)
944 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
946 while (offset < aop->coff)
949 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
956 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
962 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
964 else if (strcmp (s, "r0") == 0 ||
965 strcmp (s, "r1") == 0 ||
966 strcmp (s, "r2") == 0 ||
967 strcmp (s, "r3") == 0 ||
968 strcmp (s, "r4") == 0 ||
969 strcmp (s, "r5") == 0 ||
970 strcmp (s, "r6") == 0 ||
971 strcmp (s, "r7") == 0)
974 sprintf (buffer, "a%s", s);
975 emitcode ("mov", "@%s,%s",
976 aop->aopu.aop_ptr->name, buffer);
979 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
984 if (strcmp (s, "a") == 0)
985 emitcode ("push", "acc");
987 emitcode ("push", "%s", s);
992 /* if bit variable */
993 if (!aop->aopu.aop_dir)
995 emitcode ("clr", "a");
996 emitcode ("rlc", "a");
1001 emitcode ("clr", "%s", aop->aopu.aop_dir);
1003 emitcode ("setb", "%s", aop->aopu.aop_dir);
1004 else if (!strcmp (s, "c"))
1005 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1008 if (strcmp (s, "a"))
1013 symbol *lbl = newiTempLabel (NULL);
1014 emitcode ("clr", "c; oops");
1015 emitcode ("jz", "%05d$", lbl->key + 100);
1016 emitcode ("cpl", "c");
1017 emitcode ("", "%05d$:", lbl->key + 100);
1018 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1026 if (strcmp (aop->aopu.aop_str[offset], s))
1027 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 if (!offset && (strcmp (s, "acc") == 0))
1035 if (strcmp (aop->aopu.aop_str[offset], s))
1036 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1040 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1041 "aopPut got unsupported aop->type");
1049 /*-----------------------------------------------------------------*/
1050 /* pointToEnd :- points to the last byte of the operand */
1051 /*-----------------------------------------------------------------*/
1053 pointToEnd (asmop * aop)
1059 aop->coff = count = (aop->size - 1);
1065 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1069 emitcode ("inc", "dptr");
1076 /*-----------------------------------------------------------------*/
1077 /* reAdjustPreg - points a register back to where it should */
1078 /*-----------------------------------------------------------------*/
1080 reAdjustPreg (asmop * aop)
1082 if ((aop->coff==0) || aop->size <= 1)
1090 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1095 emitcode ("lcall", "__decdptr");
1102 #define AOP(op) op->aop
1103 #define AOP_TYPE(op) AOP(op)->type
1104 #define AOP_SIZE(op) AOP(op)->size
1105 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1106 AOP_TYPE(x) == AOP_R0))
1108 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1109 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1111 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1112 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1113 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1115 /*-----------------------------------------------------------------*/
1116 /* genNotFloat - generates not for float operations */
1117 /*-----------------------------------------------------------------*/
1119 genNotFloat (operand * op, operand * res)
1125 /* we will put 127 in the first byte of
1127 aopPut (AOP (res), "#127", 0);
1128 size = AOP_SIZE (op) - 1;
1131 l = aopGet (op->aop, offset++, FALSE, FALSE);
1136 emitcode ("orl", "a,%s",
1138 offset++, FALSE, FALSE));
1141 tlbl = newiTempLabel (NULL);
1142 aopPut (res->aop, one, 1);
1143 emitcode ("jz", "%05d$", (tlbl->key + 100));
1144 aopPut (res->aop, zero, 1);
1145 emitcode ("", "%05d$:", (tlbl->key + 100));
1147 size = res->aop->size - 2;
1149 /* put zeros in the rest */
1151 aopPut (res->aop, zero, offset++);
1154 /*-----------------------------------------------------------------*/
1155 /* opIsGptr: returns non-zero if the passed operand is */
1156 /* a generic pointer type. */
1157 /*-----------------------------------------------------------------*/
1159 opIsGptr (operand * op)
1161 sym_link *type = operandType (op);
1163 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1170 /*-----------------------------------------------------------------*/
1171 /* getDataSize - get the operand data size */
1172 /*-----------------------------------------------------------------*/
1174 getDataSize (operand * op)
1177 size = AOP_SIZE (op);
1178 if (size == GPTRSIZE)
1180 sym_link *type = operandType (op);
1181 if (IS_GENPTR (type))
1183 /* generic pointer; arithmetic operations
1184 * should ignore the high byte (pointer type).
1192 /*-----------------------------------------------------------------*/
1193 /* outAcc - output Acc */
1194 /*-----------------------------------------------------------------*/
1196 outAcc (operand * result)
1199 size = getDataSize (result);
1202 aopPut (AOP (result), "a", 0);
1205 /* unsigned or positive */
1208 aopPut (AOP (result), zero, offset++);
1213 /*-----------------------------------------------------------------*/
1214 /* outBitC - output a bit C */
1215 /*-----------------------------------------------------------------*/
1217 outBitC (operand * result)
1219 /* if the result is bit */
1220 if (AOP_TYPE (result) == AOP_CRY)
1221 aopPut (AOP (result), "c", 0);
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 /*-----------------------------------------------------------------*/
1231 /* toBoolean - emit code for orl a,operator(sizeop) */
1232 /*-----------------------------------------------------------------*/
1234 toBoolean (operand * oper)
1236 int size = AOP_SIZE (oper) - 1;
1238 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1240 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1244 /*-----------------------------------------------------------------*/
1245 /* genNot - generate code for ! operation */
1246 /*-----------------------------------------------------------------*/
1251 sym_link *optype = operandType (IC_LEFT (ic));
1253 /* assign asmOps to operand & result */
1254 aopOp (IC_LEFT (ic), ic, FALSE);
1255 aopOp (IC_RESULT (ic), ic, TRUE);
1257 /* if in bit space then a special case */
1258 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1260 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1261 emitcode ("cpl", "c");
1262 outBitC (IC_RESULT (ic));
1266 /* if type float then do float */
1267 if (IS_FLOAT (optype))
1269 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1273 toBoolean (IC_LEFT (ic));
1275 tlbl = newiTempLabel (NULL);
1276 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1277 emitcode ("", "%05d$:", tlbl->key + 100);
1278 outBitC (IC_RESULT (ic));
1281 /* release the aops */
1282 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1287 /*-----------------------------------------------------------------*/
1288 /* genCpl - generate code for complement */
1289 /*-----------------------------------------------------------------*/
1297 /* assign asmOps to operand & result */
1298 aopOp (IC_LEFT (ic), ic, FALSE);
1299 aopOp (IC_RESULT (ic), ic, TRUE);
1301 /* if both are in bit space then
1303 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1304 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1307 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1308 emitcode ("cpl", "c");
1309 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1313 size = AOP_SIZE (IC_RESULT (ic));
1316 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1318 emitcode ("cpl", "a");
1319 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1324 /* release the aops */
1325 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1329 /*-----------------------------------------------------------------*/
1330 /* genUminusFloat - unary minus for floating points */
1331 /*-----------------------------------------------------------------*/
1333 genUminusFloat (operand * op, operand * result)
1335 int size, offset = 0;
1337 /* for this we just need to flip the
1338 first it then copy the rest in place */
1339 size = AOP_SIZE (op) - 1;
1340 l = aopGet (AOP (op), 3, FALSE, FALSE);
1344 emitcode ("cpl", "acc.7");
1345 aopPut (AOP (result), "a", 3);
1349 aopPut (AOP (result),
1350 aopGet (AOP (op), offset, FALSE, FALSE),
1356 /*-----------------------------------------------------------------*/
1357 /* genUminus - unary minus code generation */
1358 /*-----------------------------------------------------------------*/
1360 genUminus (iCode * ic)
1363 sym_link *optype, *rtype;
1367 aopOp (IC_LEFT (ic), ic, FALSE);
1368 aopOp (IC_RESULT (ic), ic, TRUE);
1370 /* if both in bit space then special
1372 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1373 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1376 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1377 emitcode ("cpl", "c");
1378 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1382 optype = operandType (IC_LEFT (ic));
1383 rtype = operandType (IC_RESULT (ic));
1385 /* if float then do float stuff */
1386 if (IS_FLOAT (optype))
1388 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1392 /* otherwise subtract from zero */
1393 size = AOP_SIZE (IC_LEFT (ic));
1398 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1399 if (!strcmp (l, "a"))
1403 emitcode ("cpl", "a");
1404 emitcode ("addc", "a,#0");
1410 emitcode ("clr", "a");
1411 emitcode ("subb", "a,%s", l);
1413 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1416 /* if any remaining bytes in the result */
1417 /* we just need to propagate the sign */
1418 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1420 emitcode ("rlc", "a");
1421 emitcode ("subb", "a,acc");
1423 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1427 /* release the aops */
1428 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1429 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1432 /*-----------------------------------------------------------------*/
1433 /* saveRegisters - will look for a call and save the registers */
1434 /*-----------------------------------------------------------------*/
1436 saveRegisters (iCode * lic)
1444 for (ic = lic; ic; ic = ic->next)
1445 if (ic->op == CALL || ic->op == PCALL)
1450 fprintf (stderr, "found parameter push with no function call\n");
1454 /* if the registers have been saved already or don't need to be then
1456 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1457 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1460 /* find the registers in use at this time
1461 and push them away to safety */
1462 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1466 if (options.useXstack)
1468 if (bitVectBitValue (rsave, R0_IDX))
1469 emitcode ("mov", "b,r0");
1470 emitcode ("mov", "r0,%s", spname);
1471 for (i = 0; i < mcs51_nRegs; i++)
1473 if (bitVectBitValue (rsave, i))
1476 emitcode ("mov", "a,b");
1478 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1479 emitcode ("movx", "@r0,a");
1480 emitcode ("inc", "r0");
1483 emitcode ("mov", "%s,r0", spname);
1484 if (bitVectBitValue (rsave, R0_IDX))
1485 emitcode ("mov", "r0,b");
1488 for (i = 0; i < mcs51_nRegs; i++)
1490 if (bitVectBitValue (rsave, i))
1491 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1494 detype = getSpec (operandType (IC_LEFT (ic)));
1497 /*-----------------------------------------------------------------*/
1498 /* unsaveRegisters - pop the pushed registers */
1499 /*-----------------------------------------------------------------*/
1501 unsaveRegisters (iCode * ic)
1505 /* find the registers in use at this time
1506 and push them away to safety */
1507 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1510 if (options.useXstack)
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = mcs51_nRegs; i >= 0; i--)
1515 if (bitVectBitValue (rsave, i))
1517 emitcode ("dec", "r0");
1518 emitcode ("movx", "a,@r0");
1520 emitcode ("mov", "b,a");
1522 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1526 emitcode ("mov", "%s,r0", spname);
1527 if (bitVectBitValue (rsave, R0_IDX))
1528 emitcode ("mov", "r0,b");
1531 for (i = mcs51_nRegs; i >= 0; i--)
1533 if (bitVectBitValue (rsave, i))
1534 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1540 /*-----------------------------------------------------------------*/
1542 /*-----------------------------------------------------------------*/
1544 pushSide (operand * oper, int size)
1549 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1550 if (AOP_TYPE (oper) != AOP_REG &&
1551 AOP_TYPE (oper) != AOP_DIR &&
1554 emitcode ("mov", "a,%s", l);
1555 emitcode ("push", "acc");
1558 emitcode ("push", "%s", l);
1562 /*-----------------------------------------------------------------*/
1563 /* assignResultValue - */
1564 /*-----------------------------------------------------------------*/
1566 assignResultValue (operand * oper)
1569 int size = AOP_SIZE (oper);
1572 aopPut (AOP (oper), fReturn[offset], offset);
1578 /*-----------------------------------------------------------------*/
1579 /* genXpush - pushes onto the external stack */
1580 /*-----------------------------------------------------------------*/
1582 genXpush (iCode * ic)
1584 asmop *aop = newAsmop (0);
1586 int size, offset = 0;
1588 aopOp (IC_LEFT (ic), ic, FALSE);
1589 r = getFreePtr (ic, &aop, FALSE);
1592 emitcode ("mov", "%s,_spx", r->name);
1594 size = AOP_SIZE (IC_LEFT (ic));
1598 char *l = aopGet (AOP (IC_LEFT (ic)),
1599 offset++, FALSE, FALSE);
1601 emitcode ("movx", "@%s,a", r->name);
1602 emitcode ("inc", "%s", r->name);
1607 emitcode ("mov", "_spx,%s", r->name);
1609 freeAsmop (NULL, aop, ic, TRUE);
1610 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* genIpush - genrate code for pushing this gets a little complex */
1615 /*-----------------------------------------------------------------*/
1617 genIpush (iCode * ic)
1619 int size, offset = 0;
1622 D(emitcode (";", "genIpush"));
1624 /* if this is not a parm push : ie. it is spill push
1625 and spill push is always done on the local stack */
1629 /* and the item is spilt then do nothing */
1630 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1633 aopOp (IC_LEFT (ic), ic, FALSE);
1634 size = AOP_SIZE (IC_LEFT (ic));
1635 /* push it on the stack */
1638 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1644 emitcode ("push", "%s", l);
1649 /* this is a paramter push: in this case we call
1650 the routine to find the call and save those
1651 registers that need to be saved */
1654 /* if use external stack then call the external
1655 stack pushing routine */
1656 if (options.useXstack)
1662 /* then do the push */
1663 aopOp (IC_LEFT (ic), ic, FALSE);
1666 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1667 size = AOP_SIZE (IC_LEFT (ic));
1671 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1672 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1673 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1676 emitcode ("mov", "a,%s", l);
1677 emitcode ("push", "acc");
1680 emitcode ("push", "%s", l);
1683 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1686 /*-----------------------------------------------------------------*/
1687 /* genIpop - recover the registers: can happen only for spilling */
1688 /*-----------------------------------------------------------------*/
1690 genIpop (iCode * ic)
1695 /* if the temp was not pushed then */
1696 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1699 aopOp (IC_LEFT (ic), ic, FALSE);
1700 size = AOP_SIZE (IC_LEFT (ic));
1701 offset = (size - 1);
1703 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1709 /*-----------------------------------------------------------------*/
1710 /* unsaveRBank - restores the resgister bank from stack */
1711 /*-----------------------------------------------------------------*/
1713 unsaveRBank (int bank, iCode * ic, bool popPsw)
1719 if (options.useXstack)
1723 /* Assume r0 is available for use. */
1724 r = mcs51_regWithIdx (R0_IDX);;
1729 r = getFreePtr (ic, &aop, FALSE);
1731 emitcode ("mov", "%s,_spx", r->name);
1736 if (options.useXstack)
1738 emitcode ("movx", "a,@%s", r->name);
1739 emitcode ("mov", "psw,a");
1740 emitcode ("dec", "%s", r->name);
1744 emitcode ("pop", "psw");
1748 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1750 if (options.useXstack)
1752 emitcode ("movx", "a,@%s", r->name);
1753 emitcode ("mov", "(%s+%d),a",
1754 regs8051[i].base, 8 * bank + regs8051[i].offset);
1755 emitcode ("dec", "%s", r->name);
1759 emitcode ("pop", "(%s+%d)",
1760 regs8051[i].base, 8 * bank + regs8051[i].offset);
1763 if (options.useXstack)
1765 emitcode ("mov", "_spx,%s", r->name);
1770 freeAsmop (NULL, aop, ic, TRUE);
1774 /*-----------------------------------------------------------------*/
1775 /* saveRBank - saves an entire register bank on the stack */
1776 /*-----------------------------------------------------------------*/
1778 saveRBank (int bank, iCode * ic, bool pushPsw)
1784 if (options.useXstack)
1788 /* Assume r0 is available for use. */
1789 r = mcs51_regWithIdx (R0_IDX);;
1794 r = getFreePtr (ic, &aop, FALSE);
1796 emitcode ("mov", "%s,_spx", r->name);
1799 for (i = 0; i < mcs51_nRegs; i++)
1801 if (options.useXstack)
1803 emitcode ("inc", "%s", r->name);
1804 emitcode ("mov", "a,(%s+%d)",
1805 regs8051[i].base, 8 * bank + regs8051[i].offset);
1806 emitcode ("movx", "@%s,a", r->name);
1809 emitcode ("push", "(%s+%d)",
1810 regs8051[i].base, 8 * bank + regs8051[i].offset);
1815 if (options.useXstack)
1817 emitcode ("mov", "a,psw");
1818 emitcode ("movx", "@%s,a", r->name);
1819 emitcode ("inc", "%s", r->name);
1820 emitcode ("mov", "_spx,%s", r->name);
1825 emitcode ("push", "psw");
1828 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1833 freeAsmop (NULL, aop, ic, TRUE);
1842 /*-----------------------------------------------------------------*/
1843 /* genCall - generates a call statement */
1844 /*-----------------------------------------------------------------*/
1846 genCall (iCode * ic)
1849 bool restoreBank = FALSE;
1850 bool swapBanks = FALSE;
1852 D(emitcode(";", "genCall"));
1853 /* if send set is not empty the assign */
1858 for (sic = setFirstItem (_G.sendSet); sic;
1859 sic = setNextItem (_G.sendSet))
1861 int size, offset = 0;
1862 aopOp (IC_LEFT (sic), sic, FALSE);
1863 size = AOP_SIZE (IC_LEFT (sic));
1866 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1868 if (strcmp (l, fReturn[offset]))
1869 emitcode ("mov", "%s,%s",
1874 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1879 /* if we are calling a not _naked function that is not using
1880 the same register bank then we need to save the
1881 destination registers on the stack */
1882 detype = getSpec (operandType (IC_LEFT (ic)));
1883 if (detype && !SPEC_NAKED(detype) &&
1884 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1885 IS_ISR (currFunc->etype))
1889 /* This is unexpected; the bank should have been saved in
1892 saveRBank (SPEC_BANK (detype), ic, FALSE);
1898 /* if caller saves & we have not saved then */
1904 emitcode ("mov", "psw,#0x%02x",
1905 ((SPEC_BANK(detype)) << 3) & 0xff);
1909 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1910 OP_SYMBOL (IC_LEFT (ic))->rname :
1911 OP_SYMBOL (IC_LEFT (ic))->name));
1915 emitcode ("mov", "psw,#0x%02x",
1916 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1919 /* if we need assign a result value */
1920 if ((IS_ITEMP (IC_RESULT (ic)) &&
1921 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1922 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1923 IS_TRUE_SYMOP (IC_RESULT (ic)))
1927 aopOp (IC_RESULT (ic), ic, FALSE);
1930 assignResultValue (IC_RESULT (ic));
1932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1935 /* adjust the stack for parameters if
1940 if (ic->parmBytes > 3)
1942 emitcode ("mov", "a,%s", spname);
1943 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1944 emitcode ("mov", "%s,a", spname);
1947 for (i = 0; i < ic->parmBytes; i++)
1948 emitcode ("dec", "%s", spname);
1951 /* if we hade saved some registers then unsave them */
1952 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1953 unsaveRegisters (ic);
1955 /* if register bank was saved then pop them */
1957 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1960 /*-----------------------------------------------------------------*/
1961 /* genPcall - generates a call by pointer statement */
1962 /*-----------------------------------------------------------------*/
1964 genPcall (iCode * ic)
1967 symbol *rlbl = newiTempLabel (NULL);
1970 /* if caller saves & we have not saved then */
1974 /* if we are calling a function that is not using
1975 the same register bank then we need to save the
1976 destination registers on the stack */
1977 detype = getSpec (operandType (IC_LEFT (ic)));
1979 IS_ISR (currFunc->etype) &&
1980 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1981 saveRBank (SPEC_BANK (detype), ic, TRUE);
1984 /* push the return address on to the stack */
1985 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1986 emitcode ("push", "acc");
1987 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1988 emitcode ("push", "acc");
1990 /* now push the calling address */
1991 aopOp (IC_LEFT (ic), ic, FALSE);
1993 pushSide (IC_LEFT (ic), FPTRSIZE);
1995 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1997 /* if send set is not empty the assign */
2002 for (sic = setFirstItem (_G.sendSet); sic;
2003 sic = setNextItem (_G.sendSet))
2005 int size, offset = 0;
2006 aopOp (IC_LEFT (sic), sic, FALSE);
2007 size = AOP_SIZE (IC_LEFT (sic));
2010 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2012 if (strcmp (l, fReturn[offset]))
2013 emitcode ("mov", "%s,%s",
2018 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2023 emitcode ("ret", "");
2024 emitcode ("", "%05d$:", (rlbl->key + 100));
2027 /* if we need assign a result value */
2028 if ((IS_ITEMP (IC_RESULT (ic)) &&
2029 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2030 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2031 IS_TRUE_SYMOP (IC_RESULT (ic)))
2035 aopOp (IC_RESULT (ic), ic, FALSE);
2038 assignResultValue (IC_RESULT (ic));
2040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2043 /* adjust the stack for parameters if
2048 if (ic->parmBytes > 3)
2050 emitcode ("mov", "a,%s", spname);
2051 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2052 emitcode ("mov", "%s,a", spname);
2055 for (i = 0; i < ic->parmBytes; i++)
2056 emitcode ("dec", "%s", spname);
2060 /* if register bank was saved then unsave them */
2062 (SPEC_BANK (currFunc->etype) !=
2063 SPEC_BANK (detype)))
2064 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2066 /* if we hade saved some registers then
2069 unsaveRegisters (ic);
2073 /*-----------------------------------------------------------------*/
2074 /* resultRemat - result is rematerializable */
2075 /*-----------------------------------------------------------------*/
2077 resultRemat (iCode * ic)
2079 if (SKIP_IC (ic) || ic->op == IFX)
2082 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2084 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2085 if (sym->remat && !POINTER_SET (ic))
2092 #if defined(__BORLANDC__) || defined(_MSC_VER)
2093 #define STRCASECMP stricmp
2095 #define STRCASECMP strcasecmp
2098 /*-----------------------------------------------------------------*/
2099 /* inExcludeList - return 1 if the string is in exclude Reg list */
2100 /*-----------------------------------------------------------------*/
2102 inExcludeList (char *s)
2106 if (options.excludeRegs[i] &&
2107 STRCASECMP (options.excludeRegs[i], "none") == 0)
2110 for (i = 0; options.excludeRegs[i]; i++)
2112 if (options.excludeRegs[i] &&
2113 STRCASECMP (s, options.excludeRegs[i]) == 0)
2119 /*-----------------------------------------------------------------*/
2120 /* genFunction - generated code for function entry */
2121 /*-----------------------------------------------------------------*/
2123 genFunction (iCode * ic)
2127 bool switchedPSW = FALSE;
2130 /* create the function header */
2131 emitcode (";", "-----------------------------------------");
2132 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2133 emitcode (";", "-----------------------------------------");
2135 emitcode ("", "%s:", sym->rname);
2136 fetype = getSpec (operandType (IC_LEFT (ic)));
2138 if (SPEC_NAKED(fetype))
2140 emitcode(";", "naked function: no prologue.");
2144 /* if critical function then turn interrupts off */
2145 if (SPEC_CRTCL (fetype))
2146 emitcode ("clr", "ea");
2148 /* here we need to generate the equates for the
2149 register bank if required */
2150 if (SPEC_BANK (fetype) != rbank)
2154 rbank = SPEC_BANK (fetype);
2155 for (i = 0; i < mcs51_nRegs; i++)
2157 if (strcmp (regs8051[i].base, "0") == 0)
2158 emitcode ("", "%s = 0x%02x",
2160 8 * rbank + regs8051[i].offset);
2162 emitcode ("", "%s = %s + 0x%02x",
2165 8 * rbank + regs8051[i].offset);
2169 /* if this is an interrupt service routine then
2170 save acc, b, dpl, dph */
2171 if (IS_ISR (sym->etype))
2174 if (!inExcludeList ("acc"))
2175 emitcode ("push", "acc");
2176 if (!inExcludeList ("b"))
2177 emitcode ("push", "b");
2178 if (!inExcludeList ("dpl"))
2179 emitcode ("push", "dpl");
2180 if (!inExcludeList ("dph"))
2181 emitcode ("push", "dph");
2182 /* if this isr has no bank i.e. is going to
2183 run with bank 0 , then we need to save more
2185 if (!SPEC_BANK (sym->etype))
2188 /* if this function does not call any other
2189 function then we can be economical and
2190 save only those registers that are used */
2195 /* if any registers used */
2198 /* save the registers used */
2199 for (i = 0; i < sym->regsUsed->size; i++)
2201 if (bitVectBitValue (sym->regsUsed, i) ||
2202 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2203 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2210 /* this function has a function call cannot
2211 determines register usage so we will have to push the
2213 saveRBank (0, ic, FALSE);
2218 /* This ISR uses a non-zero bank.
2220 * We assume that the bank is available for our
2223 * However, if this ISR calls a function which uses some
2224 * other bank, we must save that bank entirely.
2226 unsigned long banksToSave = 0;
2231 #define MAX_REGISTER_BANKS 4
2236 for (i = ic; i; i = i->next)
2238 if (i->op == ENDFUNCTION)
2240 /* we got to the end OK. */
2248 detype = getSpec(operandType (IC_LEFT(i)));
2250 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2252 /* Mark this bank for saving. */
2253 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2255 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2259 banksToSave |= (1 << SPEC_BANK(detype));
2262 /* And note that we don't need to do it in
2270 /* This is a mess; we have no idea what
2271 * register bank the called function might
2274 * The only thing I can think of to do is
2275 * throw a warning and hope.
2277 werror(W_FUNCPTR_IN_USING_ISR);
2281 if (banksToSave && options.useXstack)
2283 /* Since we aren't passing it an ic,
2284 * saveRBank will assume r0 is available to abuse.
2286 * So switch to our (trashable) bank now, so
2287 * the caller's R0 isn't trashed.
2289 emitcode ("push", "psw");
2290 emitcode ("mov", "psw,#0x%02x",
2291 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2295 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2297 if (banksToSave & (1 << ix))
2299 saveRBank(ix, NULL, FALSE);
2303 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2308 /* if callee-save to be used for this function
2309 then save the registers being used in this function */
2310 if (sym->calleeSave)
2314 /* if any registers used */
2317 /* save the registers used */
2318 for (i = 0; i < sym->regsUsed->size; i++)
2320 if (bitVectBitValue (sym->regsUsed, i) ||
2321 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2323 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2331 /* set the register bank to the desired value */
2332 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2335 emitcode ("push", "psw");
2336 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2339 if (IS_RENT (sym->etype) || options.stackAuto)
2342 if (options.useXstack)
2344 emitcode ("mov", "r0,%s", spname);
2345 emitcode ("mov", "a,_bp");
2346 emitcode ("movx", "@r0,a");
2347 emitcode ("inc", "%s", spname);
2351 /* set up the stack */
2352 emitcode ("push", "_bp"); /* save the callers stack */
2354 emitcode ("mov", "_bp,%s", spname);
2357 /* adjust the stack for the function */
2363 werror (W_STACK_OVERFLOW, sym->name);
2365 if (i > 3 && sym->recvSize < 4)
2368 emitcode ("mov", "a,sp");
2369 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2370 emitcode ("mov", "sp,a");
2375 emitcode ("inc", "sp");
2381 emitcode ("mov", "a,_spx");
2382 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2383 emitcode ("mov", "_spx,a");
2388 /*-----------------------------------------------------------------*/
2389 /* genEndFunction - generates epilogue for functions */
2390 /*-----------------------------------------------------------------*/
2392 genEndFunction (iCode * ic)
2394 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2396 if (SPEC_NAKED(sym->etype))
2398 emitcode(";", "naked function: no epilogue.");
2402 if (IS_RENT (sym->etype) || options.stackAuto)
2404 emitcode ("mov", "%s,_bp", spname);
2407 /* if use external stack but some variables were
2408 added to the local stack then decrement the
2410 if (options.useXstack && sym->stack)
2412 emitcode ("mov", "a,sp");
2413 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2414 emitcode ("mov", "sp,a");
2418 if ((IS_RENT (sym->etype) || options.stackAuto))
2420 if (options.useXstack)
2422 emitcode ("mov", "r0,%s", spname);
2423 emitcode ("movx", "a,@r0");
2424 emitcode ("mov", "_bp,a");
2425 emitcode ("dec", "%s", spname);
2429 emitcode ("pop", "_bp");
2433 /* restore the register bank */
2434 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2436 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2437 || !options.useXstack)
2439 /* Special case of ISR using non-zero bank with useXstack
2442 emitcode ("pop", "psw");
2446 if (IS_ISR (sym->etype))
2449 /* now we need to restore the registers */
2450 /* if this isr has no bank i.e. is going to
2451 run with bank 0 , then we need to save more
2453 if (!SPEC_BANK (sym->etype))
2455 /* if this function does not call any other
2456 function then we can be economical and
2457 save only those registers that are used */
2462 /* if any registers used */
2465 /* save the registers used */
2466 for (i = sym->regsUsed->size; i >= 0; i--)
2468 if (bitVectBitValue (sym->regsUsed, i) ||
2469 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2470 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2477 /* this function has a function call cannot
2478 determines register usage so we will have to pop the
2480 unsaveRBank (0, ic, FALSE);
2485 /* This ISR uses a non-zero bank.
2487 * Restore any register banks saved by genFunction
2490 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2493 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2495 if (savedBanks & (1 << ix))
2497 unsaveRBank(ix, NULL, FALSE);
2501 if (options.useXstack)
2503 /* Restore bank AFTER calling unsaveRBank,
2504 * since it can trash r0.
2506 emitcode ("pop", "psw");
2510 if (!inExcludeList ("dph"))
2511 emitcode ("pop", "dph");
2512 if (!inExcludeList ("dpl"))
2513 emitcode ("pop", "dpl");
2514 if (!inExcludeList ("b"))
2515 emitcode ("pop", "b");
2516 if (!inExcludeList ("acc"))
2517 emitcode ("pop", "acc");
2519 if (SPEC_CRTCL (sym->etype))
2520 emitcode ("setb", "ea");
2522 /* if debug then send end of function */
2523 /* if (options.debug && currFunc) */
2524 if (options.debug && currFunc)
2527 emitcode ("", "C$%s$%d$%d$%d ==.",
2528 FileBaseName (ic->filename), currFunc->lastLine,
2529 ic->level, ic->block);
2530 if (IS_STATIC (currFunc->etype))
2531 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2533 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2537 emitcode ("reti", "");
2541 if (SPEC_CRTCL (sym->etype))
2542 emitcode ("setb", "ea");
2544 if (sym->calleeSave)
2548 /* if any registers used */
2551 /* save the registers used */
2552 for (i = sym->regsUsed->size; i >= 0; i--)
2554 if (bitVectBitValue (sym->regsUsed, i) ||
2555 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2556 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2562 /* if debug then send end of function */
2563 if (options.debug && currFunc)
2566 emitcode ("", "C$%s$%d$%d$%d ==.",
2567 FileBaseName (ic->filename), currFunc->lastLine,
2568 ic->level, ic->block);
2569 if (IS_STATIC (currFunc->etype))
2570 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2572 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2576 emitcode ("ret", "");
2581 /*-----------------------------------------------------------------*/
2582 /* genRet - generate code for return statement */
2583 /*-----------------------------------------------------------------*/
2587 int size, offset = 0, pushed = 0;
2589 /* if we have no return value then
2590 just generate the "ret" */
2594 /* we have something to return then
2595 move the return value into place */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2597 size = AOP_SIZE (IC_LEFT (ic));
2602 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2605 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2607 emitcode ("push", "%s", l);
2612 l = aopGet (AOP (IC_LEFT (ic)), offset,
2614 if (strcmp (fReturn[offset], l))
2615 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2624 if (strcmp (fReturn[pushed], "a"))
2625 emitcode ("pop", fReturn[pushed]);
2627 emitcode ("pop", "acc");
2630 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2633 /* generate a jump to the return label
2634 if the next is not the return statement */
2635 if (!(ic->next && ic->next->op == LABEL &&
2636 IC_LABEL (ic->next) == returnLabel))
2638 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2642 /*-----------------------------------------------------------------*/
2643 /* genLabel - generates a label */
2644 /*-----------------------------------------------------------------*/
2646 genLabel (iCode * ic)
2648 /* special case never generate */
2649 if (IC_LABEL (ic) == entryLabel)
2652 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2655 /*-----------------------------------------------------------------*/
2656 /* genGoto - generates a ljmp */
2657 /*-----------------------------------------------------------------*/
2659 genGoto (iCode * ic)
2661 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2664 /*-----------------------------------------------------------------*/
2665 /* findLabelBackwards: walks back through the iCode chain looking */
2666 /* for the given label. Returns number of iCode instructions */
2667 /* between that label and given ic. */
2668 /* Returns zero if label not found. */
2669 /*-----------------------------------------------------------------*/
2671 findLabelBackwards (iCode * ic, int key)
2680 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2682 /* printf("findLabelBackwards = %d\n", count); */
2690 /*-----------------------------------------------------------------*/
2691 /* genPlusIncr :- does addition with increment if possible */
2692 /*-----------------------------------------------------------------*/
2694 genPlusIncr (iCode * ic)
2696 unsigned int icount;
2697 unsigned int size = getDataSize (IC_RESULT (ic));
2699 /* will try to generate an increment */
2700 /* if the right side is not a literal
2702 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2705 /* if the literal value of the right hand side
2706 is greater than 4 then it is not worth it */
2707 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2710 /* if increment 16 bits in register */
2711 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2719 /* If the next instruction is a goto and the goto target
2720 * is < 10 instructions previous to this, we can generate
2721 * jumps straight to that target.
2723 if (ic->next && ic->next->op == GOTO
2724 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2725 && labelRange <= 10)
2727 emitcode (";", "tail increment optimized");
2728 tlbl = IC_LABEL (ic->next);
2733 tlbl = newiTempLabel (NULL);
2736 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2737 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2738 IS_AOP_PREG (IC_RESULT (ic)))
2739 emitcode ("cjne", "%s,#0x00,%05d$"
2740 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2744 emitcode ("clr", "a");
2745 emitcode ("cjne", "a,%s,%05d$"
2746 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2750 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2753 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2754 IS_AOP_PREG (IC_RESULT (ic)))
2755 emitcode ("cjne", "%s,#0x00,%05d$"
2756 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2759 emitcode ("cjne", "a,%s,%05d$"
2760 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2763 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2767 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2768 IS_AOP_PREG (IC_RESULT (ic)))
2769 emitcode ("cjne", "%s,#0x00,%05d$"
2770 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2774 emitcode ("cjne", "a,%s,%05d$"
2775 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2778 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2783 emitcode ("", "%05d$:", tlbl->key + 100);
2788 /* if the sizes are greater than 1 then we cannot */
2789 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2790 AOP_SIZE (IC_LEFT (ic)) > 1)
2793 /* we can if the aops of the left & result match or
2794 if they are in registers and the registers are the
2796 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2801 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2802 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2803 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2809 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2818 /*-----------------------------------------------------------------*/
2819 /* outBitAcc - output a bit in acc */
2820 /*-----------------------------------------------------------------*/
2822 outBitAcc (operand * result)
2824 symbol *tlbl = newiTempLabel (NULL);
2825 /* if the result is a bit */
2826 if (AOP_TYPE (result) == AOP_CRY)
2828 aopPut (AOP (result), "a", 0);
2832 emitcode ("jz", "%05d$", tlbl->key + 100);
2833 emitcode ("mov", "a,%s", one);
2834 emitcode ("", "%05d$:", tlbl->key + 100);
2839 /*-----------------------------------------------------------------*/
2840 /* genPlusBits - generates code for addition of two bits */
2841 /*-----------------------------------------------------------------*/
2843 genPlusBits (iCode * ic)
2845 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2847 symbol *lbl = newiTempLabel (NULL);
2848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2849 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2850 emitcode ("cpl", "c");
2851 emitcode ("", "%05d$:", (lbl->key + 100));
2852 outBitC (IC_RESULT (ic));
2856 emitcode ("clr", "a");
2857 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2858 emitcode ("rlc", "a");
2859 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2860 emitcode ("addc", "a,#0x00");
2861 outAcc (IC_RESULT (ic));
2866 /* This is the original version of this code.
2868 * This is being kept around for reference,
2869 * because I am not entirely sure I got it right...
2872 adjustArithmeticResult (iCode * ic)
2874 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2875 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2876 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2877 aopPut (AOP (IC_RESULT (ic)),
2878 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2881 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2882 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2883 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2884 aopPut (AOP (IC_RESULT (ic)),
2885 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2888 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2889 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2890 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2891 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2892 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2895 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2896 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2900 /* This is the pure and virtuous version of this code.
2901 * I'm pretty certain it's right, but not enough to toss the old
2905 adjustArithmeticResult (iCode * ic)
2907 if (opIsGptr (IC_RESULT (ic)) &&
2908 opIsGptr (IC_LEFT (ic)) &&
2909 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2911 aopPut (AOP (IC_RESULT (ic)),
2912 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2916 if (opIsGptr (IC_RESULT (ic)) &&
2917 opIsGptr (IC_RIGHT (ic)) &&
2918 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2920 aopPut (AOP (IC_RESULT (ic)),
2921 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2925 if (opIsGptr (IC_RESULT (ic)) &&
2926 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2927 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2928 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2932 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2933 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2938 /*-----------------------------------------------------------------*/
2939 /* genPlus - generates code for addition */
2940 /*-----------------------------------------------------------------*/
2942 genPlus (iCode * ic)
2944 int size, offset = 0;
2946 /* special cases :- */
2948 aopOp (IC_LEFT (ic), ic, FALSE);
2949 aopOp (IC_RIGHT (ic), ic, FALSE);
2950 aopOp (IC_RESULT (ic), ic, TRUE);
2952 /* if literal, literal on the right or
2953 if left requires ACC or right is already
2955 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2956 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2957 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2959 operand *t = IC_RIGHT (ic);
2960 IC_RIGHT (ic) = IC_LEFT (ic);
2964 /* if both left & right are in bit
2966 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2967 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2973 /* if left in bit space & right literal */
2974 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2975 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2977 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2978 /* if result in bit space */
2979 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2981 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2982 emitcode ("cpl", "c");
2983 outBitC (IC_RESULT (ic));
2987 size = getDataSize (IC_RESULT (ic));
2990 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2991 emitcode ("addc", "a,#00");
2992 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2998 /* if I can do an increment instead
2999 of add then GOOD for ME */
3000 if (genPlusIncr (ic) == TRUE)
3003 size = getDataSize (IC_RESULT (ic));
3007 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3009 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3011 emitcode ("add", "a,%s",
3012 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3014 emitcode ("addc", "a,%s",
3015 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3019 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3021 emitcode ("add", "a,%s",
3022 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3024 emitcode ("addc", "a,%s",
3025 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3027 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3030 adjustArithmeticResult (ic);
3033 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3034 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3035 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3038 /*-----------------------------------------------------------------*/
3039 /* genMinusDec :- does subtraction with deccrement if possible */
3040 /*-----------------------------------------------------------------*/
3042 genMinusDec (iCode * ic)
3044 unsigned int icount;
3045 unsigned int size = getDataSize (IC_RESULT (ic));
3047 /* will try to generate an increment */
3048 /* if the right side is not a literal
3050 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3053 /* if the literal value of the right hand side
3054 is greater than 4 then it is not worth it */
3055 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3058 /* if decrement 16 bits in register */
3059 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3067 /* If the next instruction is a goto and the goto target
3068 * is <= 10 instructions previous to this, we can generate
3069 * jumps straight to that target.
3071 if (ic->next && ic->next->op == GOTO
3072 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3073 && labelRange <= 10)
3075 emitcode (";", "tail decrement optimized");
3076 tlbl = IC_LABEL (ic->next);
3081 tlbl = newiTempLabel (NULL);
3085 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3086 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3087 IS_AOP_PREG (IC_RESULT (ic)))
3088 emitcode ("cjne", "%s,#0xff,%05d$"
3089 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3093 emitcode ("mov", "a,#0xff");
3094 emitcode ("cjne", "a,%s,%05d$"
3095 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3098 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3101 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3102 IS_AOP_PREG (IC_RESULT (ic)))
3103 emitcode ("cjne", "%s,#0xff,%05d$"
3104 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3108 emitcode ("cjne", "a,%s,%05d$"
3109 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3112 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3116 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3117 IS_AOP_PREG (IC_RESULT (ic)))
3118 emitcode ("cjne", "%s,#0xff,%05d$"
3119 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3123 emitcode ("cjne", "a,%s,%05d$"
3124 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3127 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3131 emitcode ("", "%05d$:", tlbl->key + 100);
3136 /* if the sizes are greater than 1 then we cannot */
3137 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3138 AOP_SIZE (IC_LEFT (ic)) > 1)
3141 /* we can if the aops of the left & result match or
3142 if they are in registers and the registers are the
3144 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3148 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3156 /*-----------------------------------------------------------------*/
3157 /* addSign - complete with sign */
3158 /*-----------------------------------------------------------------*/
3160 addSign (operand * result, int offset, int sign)
3162 int size = (getDataSize (result) - offset);
3167 emitcode ("rlc", "a");
3168 emitcode ("subb", "a,acc");
3170 aopPut (AOP (result), "a", offset++);
3174 aopPut (AOP (result), zero, offset++);
3178 /*-----------------------------------------------------------------*/
3179 /* genMinusBits - generates code for subtraction of two bits */
3180 /*-----------------------------------------------------------------*/
3182 genMinusBits (iCode * ic)
3184 symbol *lbl = newiTempLabel (NULL);
3185 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3187 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3188 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3189 emitcode ("cpl", "c");
3190 emitcode ("", "%05d$:", (lbl->key + 100));
3191 outBitC (IC_RESULT (ic));
3195 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3196 emitcode ("subb", "a,acc");
3197 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3198 emitcode ("inc", "a");
3199 emitcode ("", "%05d$:", (lbl->key + 100));
3200 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3201 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3205 /*-----------------------------------------------------------------*/
3206 /* genMinus - generates code for subtraction */
3207 /*-----------------------------------------------------------------*/
3209 genMinus (iCode * ic)
3211 int size, offset = 0;
3212 unsigned long lit = 0L;
3214 aopOp (IC_LEFT (ic), ic, FALSE);
3215 aopOp (IC_RIGHT (ic), ic, FALSE);
3216 aopOp (IC_RESULT (ic), ic, TRUE);
3218 /* special cases :- */
3219 /* if both left & right are in bit space */
3220 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3221 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3227 /* if I can do an decrement instead
3228 of subtract then GOOD for ME */
3229 if (genMinusDec (ic) == TRUE)
3232 size = getDataSize (IC_RESULT (ic));
3234 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3240 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3244 /* if literal, add a,#-lit, else normal subb */
3247 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3248 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3249 emitcode ("subb", "a,%s",
3250 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3253 /* first add without previous c */
3255 if (!size && lit==-1) {
3256 emitcode ("dec", "a");
3258 emitcode ("add", "a,#0x%02x",
3259 (unsigned int) (lit & 0x0FFL));
3262 emitcode ("addc", "a,#0x%02x",
3263 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3266 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3269 adjustArithmeticResult (ic);
3272 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3273 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3274 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3278 /*-----------------------------------------------------------------*/
3279 /* genMultbits :- multiplication of bits */
3280 /*-----------------------------------------------------------------*/
3282 genMultbits (operand * left,
3286 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3287 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3292 /*-----------------------------------------------------------------*/
3293 /* genMultOneByte : 8*8=8/16 bit multiplication */
3294 /*-----------------------------------------------------------------*/
3296 genMultOneByte (operand * left,
3300 sym_link *opetype = operandType (result);
3302 int size=AOP_SIZE(result);
3304 if (size<1 || size>2) {
3305 // this should never happen
3306 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3307 AOP_SIZE(result), __FILE__, lineno);
3311 /* (if two literals: the value is computed before) */
3312 /* if one literal, literal on the right */
3313 if (AOP_TYPE (left) == AOP_LIT)
3318 //emitcode (";", "swapped left and right");
3321 if (SPEC_USIGN(opetype)
3322 // ignore the sign of left and right, what else can we do?
3323 || (SPEC_USIGN(operandType(left)) &&
3324 SPEC_USIGN(operandType(right)))) {
3325 // just an unsigned 8*8=8/16 multiply
3326 //emitcode (";","unsigned");
3327 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3328 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3329 emitcode ("mul", "ab");
3330 aopPut (AOP (result), "a", 0);
3332 aopPut (AOP (result), "b", 1);
3337 // we have to do a signed multiply
3339 //emitcode (";", "signed");
3340 emitcode ("clr", "F0"); // reset sign flag
3341 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3343 lbl=newiTempLabel(NULL);
3344 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3345 // left side is negative, 8-bit two's complement, this fails for -128
3346 emitcode ("setb", "F0"); // set sign flag
3347 emitcode ("cpl", "a");
3348 emitcode ("inc", "a");
3350 emitcode ("", "%05d$:", lbl->key+100);
3353 if (AOP_TYPE(right)==AOP_LIT) {
3354 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3355 /* AND literal negative */
3357 emitcode ("cpl", "F0"); // complement sign flag
3358 emitcode ("mov", "b,#0x%02x", -val);
3360 emitcode ("mov", "b,#0x%02x", val);
3363 lbl=newiTempLabel(NULL);
3364 emitcode ("mov", "b,a");
3365 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3366 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3367 // right side is negative, 8-bit two's complement
3368 emitcode ("cpl", "F0"); // complement sign flag
3369 emitcode ("cpl", "a");
3370 emitcode ("inc", "a");
3371 emitcode ("", "%05d$:", lbl->key+100);
3373 emitcode ("mul", "ab");
3375 lbl=newiTempLabel(NULL);
3376 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3377 // only ONE op was negative, we have to do a 8/16-bit two's complement
3378 emitcode ("cpl", "a"); // lsb
3380 emitcode ("inc", "a");
3382 emitcode ("add", "a,#1");
3383 emitcode ("xch", "a,b");
3384 emitcode ("cpl", "a"); // msb
3385 emitcode ("addc", "a,#0");
3386 emitcode ("xch", "a,b");
3389 emitcode ("", "%05d$:", lbl->key+100);
3390 aopPut (AOP (result), "a", 0);
3392 aopPut (AOP (result), "b", 1);
3396 /*-----------------------------------------------------------------*/
3397 /* genMult - generates code for multiplication */
3398 /*-----------------------------------------------------------------*/
3400 genMult (iCode * ic)
3402 operand *left = IC_LEFT (ic);
3403 operand *right = IC_RIGHT (ic);
3404 operand *result = IC_RESULT (ic);
3406 /* assign the amsops */
3407 aopOp (left, ic, FALSE);
3408 aopOp (right, ic, FALSE);
3409 aopOp (result, ic, TRUE);
3411 /* special cases first */
3413 if (AOP_TYPE (left) == AOP_CRY &&
3414 AOP_TYPE (right) == AOP_CRY)
3416 genMultbits (left, right, result);
3420 /* if both are of size == 1 */
3421 if (AOP_SIZE (left) == 1 &&
3422 AOP_SIZE (right) == 1)
3424 genMultOneByte (left, right, result);
3428 /* should have been converted to function call */
3432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3434 freeAsmop (result, NULL, ic, TRUE);
3437 /*-----------------------------------------------------------------*/
3438 /* genDivbits :- division of bits */
3439 /*-----------------------------------------------------------------*/
3441 genDivbits (operand * left,
3448 /* the result must be bit */
3449 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3450 l = aopGet (AOP (left), 0, FALSE, FALSE);
3454 emitcode ("div", "ab");
3455 emitcode ("rrc", "a");
3456 aopPut (AOP (result), "c", 0);
3459 /*-----------------------------------------------------------------*/
3460 /* genDivOneByte : 8 bit division */
3461 /*-----------------------------------------------------------------*/
3463 genDivOneByte (operand * left,
3467 sym_link *opetype = operandType (result);
3472 size = AOP_SIZE (result) - 1;
3474 /* signed or unsigned */
3475 if (SPEC_USIGN (opetype))
3477 /* unsigned is easy */
3478 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3479 l = aopGet (AOP (left), 0, FALSE, FALSE);
3481 emitcode ("div", "ab");
3482 aopPut (AOP (result), "a", 0);
3484 aopPut (AOP (result), zero, offset++);
3488 /* signed is a little bit more difficult */
3490 /* save the signs of the operands */
3491 l = aopGet (AOP (left), 0, FALSE, FALSE);
3493 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3494 emitcode ("push", "acc"); /* save it on the stack */
3496 /* now sign adjust for both left & right */
3497 l = aopGet (AOP (right), 0, FALSE, FALSE);
3499 lbl = newiTempLabel (NULL);
3500 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3501 emitcode ("cpl", "a");
3502 emitcode ("inc", "a");
3503 emitcode ("", "%05d$:", (lbl->key + 100));
3504 emitcode ("mov", "b,a");
3506 /* sign adjust left side */
3507 l = aopGet (AOP (left), 0, FALSE, FALSE);
3510 lbl = newiTempLabel (NULL);
3511 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3512 emitcode ("cpl", "a");
3513 emitcode ("inc", "a");
3514 emitcode ("", "%05d$:", (lbl->key + 100));
3516 /* now the division */
3517 emitcode ("div", "ab");
3518 /* we are interested in the lower order
3520 emitcode ("mov", "b,a");
3521 lbl = newiTempLabel (NULL);
3522 emitcode ("pop", "acc");
3523 /* if there was an over flow we don't
3524 adjust the sign of the result */
3525 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3526 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3528 emitcode ("clr", "a");
3529 emitcode ("subb", "a,b");
3530 emitcode ("mov", "b,a");
3531 emitcode ("", "%05d$:", (lbl->key + 100));
3533 /* now we are done */
3534 aopPut (AOP (result), "b", 0);
3537 emitcode ("mov", "c,b.7");
3538 emitcode ("subb", "a,acc");
3541 aopPut (AOP (result), "a", offset++);
3545 /*-----------------------------------------------------------------*/
3546 /* genDiv - generates code for division */
3547 /*-----------------------------------------------------------------*/
3551 operand *left = IC_LEFT (ic);
3552 operand *right = IC_RIGHT (ic);
3553 operand *result = IC_RESULT (ic);
3555 /* assign the amsops */
3556 aopOp (left, ic, FALSE);
3557 aopOp (right, ic, FALSE);
3558 aopOp (result, ic, TRUE);
3560 /* special cases first */
3562 if (AOP_TYPE (left) == AOP_CRY &&
3563 AOP_TYPE (right) == AOP_CRY)
3565 genDivbits (left, right, result);
3569 /* if both are of size == 1 */
3570 if (AOP_SIZE (left) == 1 &&
3571 AOP_SIZE (right) == 1)
3573 genDivOneByte (left, right, result);
3577 /* should have been converted to function call */
3580 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3581 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3582 freeAsmop (result, NULL, ic, TRUE);
3585 /*-----------------------------------------------------------------*/
3586 /* genModbits :- modulus of bits */
3587 /*-----------------------------------------------------------------*/
3589 genModbits (operand * left,
3596 /* the result must be bit */
3597 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3598 l = aopGet (AOP (left), 0, FALSE, FALSE);
3602 emitcode ("div", "ab");
3603 emitcode ("mov", "a,b");
3604 emitcode ("rrc", "a");
3605 aopPut (AOP (result), "c", 0);
3608 /*-----------------------------------------------------------------*/
3609 /* genModOneByte : 8 bit modulus */
3610 /*-----------------------------------------------------------------*/
3612 genModOneByte (operand * left,
3616 sym_link *opetype = operandType (result);
3620 /* signed or unsigned */
3621 if (SPEC_USIGN (opetype))
3623 /* unsigned is easy */
3624 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3625 l = aopGet (AOP (left), 0, FALSE, FALSE);
3627 emitcode ("div", "ab");
3628 aopPut (AOP (result), "b", 0);
3632 /* signed is a little bit more difficult */
3634 /* save the signs of the operands */
3635 l = aopGet (AOP (left), 0, FALSE, FALSE);
3638 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3639 emitcode ("push", "acc"); /* save it on the stack */
3641 /* now sign adjust for both left & right */
3642 l = aopGet (AOP (right), 0, FALSE, FALSE);
3645 lbl = newiTempLabel (NULL);
3646 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3647 emitcode ("cpl", "a");
3648 emitcode ("inc", "a");
3649 emitcode ("", "%05d$:", (lbl->key + 100));
3650 emitcode ("mov", "b,a");
3652 /* sign adjust left side */
3653 l = aopGet (AOP (left), 0, FALSE, FALSE);
3656 lbl = newiTempLabel (NULL);
3657 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3658 emitcode ("cpl", "a");
3659 emitcode ("inc", "a");
3660 emitcode ("", "%05d$:", (lbl->key + 100));
3662 /* now the multiplication */
3663 emitcode ("div", "ab");
3664 /* we are interested in the lower order
3666 lbl = newiTempLabel (NULL);
3667 emitcode ("pop", "acc");
3668 /* if there was an over flow we don't
3669 adjust the sign of the result */
3670 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3671 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3673 emitcode ("clr", "a");
3674 emitcode ("subb", "a,b");
3675 emitcode ("mov", "b,a");
3676 emitcode ("", "%05d$:", (lbl->key + 100));
3678 /* now we are done */
3679 aopPut (AOP (result), "b", 0);
3683 /*-----------------------------------------------------------------*/
3684 /* genMod - generates code for division */
3685 /*-----------------------------------------------------------------*/
3689 operand *left = IC_LEFT (ic);
3690 operand *right = IC_RIGHT (ic);
3691 operand *result = IC_RESULT (ic);
3693 /* assign the amsops */
3694 aopOp (left, ic, FALSE);
3695 aopOp (right, ic, FALSE);
3696 aopOp (result, ic, TRUE);
3698 /* special cases first */
3700 if (AOP_TYPE (left) == AOP_CRY &&
3701 AOP_TYPE (right) == AOP_CRY)
3703 genModbits (left, right, result);
3707 /* if both are of size == 1 */
3708 if (AOP_SIZE (left) == 1 &&
3709 AOP_SIZE (right) == 1)
3711 genModOneByte (left, right, result);
3715 /* should have been converted to function call */
3719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3721 freeAsmop (result, NULL, ic, TRUE);
3724 /*-----------------------------------------------------------------*/
3725 /* genIfxJump :- will create a jump depending on the ifx */
3726 /*-----------------------------------------------------------------*/
3728 genIfxJump (iCode * ic, char *jval)
3731 symbol *tlbl = newiTempLabel (NULL);
3734 /* if true label then we jump if condition
3738 jlbl = IC_TRUE (ic);
3739 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3740 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3744 /* false label is present */
3745 jlbl = IC_FALSE (ic);
3746 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3747 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3749 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3750 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3752 emitcode (inst, "%05d$", tlbl->key + 100);
3753 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3754 emitcode ("", "%05d$:", tlbl->key + 100);
3756 /* mark the icode as generated */
3760 /*-----------------------------------------------------------------*/
3761 /* genCmp :- greater or less than comparison */
3762 /*-----------------------------------------------------------------*/
3764 genCmp (operand * left, operand * right,
3765 operand * result, iCode * ifx, int sign, iCode *ic)
3767 int size, offset = 0;
3768 unsigned long lit = 0L;
3770 /* if left & right are bit variables */
3771 if (AOP_TYPE (left) == AOP_CRY &&
3772 AOP_TYPE (right) == AOP_CRY)
3774 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3775 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3779 /* subtract right from left if at the
3780 end the carry flag is set then we know that
3781 left is greater than right */
3782 size = max (AOP_SIZE (left), AOP_SIZE (right));
3784 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3785 if ((size == 1) && !sign &&
3786 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3788 symbol *lbl = newiTempLabel (NULL);
3789 emitcode ("cjne", "%s,%s,%05d$",
3790 aopGet (AOP (left), offset, FALSE, FALSE),
3791 aopGet (AOP (right), offset, FALSE, FALSE),
3793 emitcode ("", "%05d$:", lbl->key + 100);
3797 if (AOP_TYPE (right) == AOP_LIT)
3799 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3800 /* optimize if(x < 0) or if(x >= 0) */
3809 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3810 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3812 genIfxJump (ifx, "acc.7");
3816 emitcode ("rlc", "a");
3824 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3825 if (sign && size == 0)
3827 emitcode ("xrl", "a,#0x80");
3828 if (AOP_TYPE (right) == AOP_LIT)
3830 unsigned long lit = (unsigned long)
3831 floatFromVal (AOP (right)->aopu.aop_lit);
3832 emitcode ("subb", "a,#0x%02x",
3833 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3837 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3838 emitcode ("xrl", "b,#0x80");
3839 emitcode ("subb", "a,b");
3843 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3851 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3857 /* if the result is used in the next
3858 ifx conditional branch then generate
3859 code a little differently */
3861 genIfxJump (ifx, "c");
3864 /* leave the result in acc */
3868 /*-----------------------------------------------------------------*/
3869 /* genCmpGt :- greater than comparison */
3870 /*-----------------------------------------------------------------*/
3872 genCmpGt (iCode * ic, iCode * ifx)
3874 operand *left, *right, *result;
3875 sym_link *letype, *retype;
3878 left = IC_LEFT (ic);
3879 right = IC_RIGHT (ic);
3880 result = IC_RESULT (ic);
3882 letype = getSpec (operandType (left));
3883 retype = getSpec (operandType (right));
3884 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3885 /* assign the amsops */
3886 aopOp (left, ic, FALSE);
3887 aopOp (right, ic, FALSE);
3888 aopOp (result, ic, TRUE);
3890 genCmp (right, left, result, ifx, sign,ic);
3892 freeAsmop (result, NULL, ic, TRUE);
3895 /*-----------------------------------------------------------------*/
3896 /* genCmpLt - less than comparisons */
3897 /*-----------------------------------------------------------------*/
3899 genCmpLt (iCode * ic, iCode * ifx)
3901 operand *left, *right, *result;
3902 sym_link *letype, *retype;
3905 left = IC_LEFT (ic);
3906 right = IC_RIGHT (ic);
3907 result = IC_RESULT (ic);
3909 letype = getSpec (operandType (left));
3910 retype = getSpec (operandType (right));
3911 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3913 /* assign the amsops */
3914 aopOp (left, ic, FALSE);
3915 aopOp (right, ic, FALSE);
3916 aopOp (result, ic, TRUE);
3918 genCmp (left, right, result, ifx, sign,ic);
3920 freeAsmop (result, NULL, ic, TRUE);
3923 /*-----------------------------------------------------------------*/
3924 /* gencjneshort - compare and jump if not equal */
3925 /*-----------------------------------------------------------------*/
3927 gencjneshort (operand * left, operand * right, symbol * lbl)
3929 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3931 unsigned long lit = 0L;
3933 /* if the left side is a literal or
3934 if the right is in a pointer register and left
3936 if ((AOP_TYPE (left) == AOP_LIT) ||
3937 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3943 if (AOP_TYPE (right) == AOP_LIT)
3944 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3946 /* if the right side is a literal then anything goes */
3947 if (AOP_TYPE (right) == AOP_LIT &&
3948 AOP_TYPE (left) != AOP_DIR)
3952 emitcode ("cjne", "%s,%s,%05d$",
3953 aopGet (AOP (left), offset, FALSE, FALSE),
3954 aopGet (AOP (right), offset, FALSE, FALSE),
3960 /* if the right side is in a register or in direct space or
3961 if the left is a pointer register & right is not */
3962 else if (AOP_TYPE (right) == AOP_REG ||
3963 AOP_TYPE (right) == AOP_DIR ||
3964 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3965 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3969 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3970 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3971 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3972 emitcode ("jnz", "%05d$", lbl->key + 100);
3974 emitcode ("cjne", "a,%s,%05d$",
3975 aopGet (AOP (right), offset, FALSE, TRUE),
3982 /* right is a pointer reg need both a & b */
3985 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3986 if (strcmp (l, "b"))
3987 emitcode ("mov", "b,%s", l);
3988 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3989 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3995 /*-----------------------------------------------------------------*/
3996 /* gencjne - compare and jump if not equal */
3997 /*-----------------------------------------------------------------*/
3999 gencjne (operand * left, operand * right, symbol * lbl)
4001 symbol *tlbl = newiTempLabel (NULL);
4003 gencjneshort (left, right, lbl);
4005 emitcode ("mov", "a,%s", one);
4006 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4007 emitcode ("", "%05d$:", lbl->key + 100);
4008 emitcode ("clr", "a");
4009 emitcode ("", "%05d$:", tlbl->key + 100);
4012 /*-----------------------------------------------------------------*/
4013 /* genCmpEq - generates code for equal to */
4014 /*-----------------------------------------------------------------*/
4016 genCmpEq (iCode * ic, iCode * ifx)
4018 operand *left, *right, *result;
4020 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4021 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4022 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4024 /* if literal, literal on the right or
4025 if the right is in a pointer register and left
4027 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4028 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4030 operand *t = IC_RIGHT (ic);
4031 IC_RIGHT (ic) = IC_LEFT (ic);
4035 if (ifx && !AOP_SIZE (result))
4038 /* if they are both bit variables */
4039 if (AOP_TYPE (left) == AOP_CRY &&
4040 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4042 if (AOP_TYPE (right) == AOP_LIT)
4044 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4048 emitcode ("cpl", "c");
4052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056 emitcode ("clr", "c");
4058 /* AOP_TYPE(right) == AOP_CRY */
4062 symbol *lbl = newiTempLabel (NULL);
4063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4064 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4065 emitcode ("cpl", "c");
4066 emitcode ("", "%05d$:", (lbl->key + 100));
4068 /* if true label then we jump if condition
4070 tlbl = newiTempLabel (NULL);
4073 emitcode ("jnc", "%05d$", tlbl->key + 100);
4074 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4078 emitcode ("jc", "%05d$", tlbl->key + 100);
4079 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4081 emitcode ("", "%05d$:", tlbl->key + 100);
4085 tlbl = newiTempLabel (NULL);
4086 gencjneshort (left, right, tlbl);
4089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4090 emitcode ("", "%05d$:", tlbl->key + 100);
4094 symbol *lbl = newiTempLabel (NULL);
4095 emitcode ("sjmp", "%05d$", lbl->key + 100);
4096 emitcode ("", "%05d$:", tlbl->key + 100);
4097 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4098 emitcode ("", "%05d$:", lbl->key + 100);
4101 /* mark the icode as generated */
4106 /* if they are both bit variables */
4107 if (AOP_TYPE (left) == AOP_CRY &&
4108 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4110 if (AOP_TYPE (right) == AOP_LIT)
4112 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4116 emitcode ("cpl", "c");
4120 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4124 emitcode ("clr", "c");
4126 /* AOP_TYPE(right) == AOP_CRY */
4130 symbol *lbl = newiTempLabel (NULL);
4131 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4132 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4133 emitcode ("cpl", "c");
4134 emitcode ("", "%05d$:", (lbl->key + 100));
4137 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4144 genIfxJump (ifx, "c");
4147 /* if the result is used in an arithmetic operation
4148 then put the result in place */
4153 gencjne (left, right, newiTempLabel (NULL));
4154 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4156 aopPut (AOP (result), "a", 0);
4161 genIfxJump (ifx, "a");
4164 /* if the result is used in an arithmetic operation
4165 then put the result in place */
4166 if (AOP_TYPE (result) != AOP_CRY)
4168 /* leave the result in acc */
4172 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4173 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4174 freeAsmop (result, NULL, ic, TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* ifxForOp - returns the icode containing the ifx for operand */
4179 /*-----------------------------------------------------------------*/
4181 ifxForOp (operand * op, iCode * ic)
4183 /* if true symbol then needs to be assigned */
4184 if (IS_TRUE_SYMOP (op))
4187 /* if this has register type condition and
4188 the next instruction is ifx with the same operand
4189 and live to of the operand is upto the ifx only then */
4191 ic->next->op == IFX &&
4192 IC_COND (ic->next)->key == op->key &&
4193 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4199 /*-----------------------------------------------------------------*/
4200 /* hasInc - operand is incremented before any other use */
4201 /*-----------------------------------------------------------------*/
4203 hasInc (operand *op, iCode *ic)
4205 sym_link *type = operandType(op);
4206 sym_link *retype = getSpec (type);
4207 iCode *lic = ic->next;
4210 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4211 isize = getSize(type->next);
4213 /* if operand of the form op = op + <sizeof *op> */
4214 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4215 isOperandEqual(IC_RESULT(lic),op) &&
4216 isOperandLiteral(IC_RIGHT(lic)) &&
4217 operandLitValue(IC_RIGHT(lic)) == isize) {
4220 /* if the operand used or deffed */
4221 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4229 /*-----------------------------------------------------------------*/
4230 /* genAndOp - for && operation */
4231 /*-----------------------------------------------------------------*/
4233 genAndOp (iCode * ic)
4235 operand *left, *right, *result;
4238 /* note here that && operations that are in an
4239 if statement are taken away by backPatchLabels
4240 only those used in arthmetic operations remain */
4241 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4242 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4243 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4245 /* if both are bit variables */
4246 if (AOP_TYPE (left) == AOP_CRY &&
4247 AOP_TYPE (right) == AOP_CRY)
4249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4250 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4255 tlbl = newiTempLabel (NULL);
4257 emitcode ("jz", "%05d$", tlbl->key + 100);
4259 emitcode ("", "%05d$:", tlbl->key + 100);
4263 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4265 freeAsmop (result, NULL, ic, TRUE);
4269 /*-----------------------------------------------------------------*/
4270 /* genOrOp - for || operation */
4271 /*-----------------------------------------------------------------*/
4273 genOrOp (iCode * ic)
4275 operand *left, *right, *result;
4278 /* note here that || operations that are in an
4279 if statement are taken away by backPatchLabels
4280 only those used in arthmetic operations remain */
4281 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4282 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4283 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4285 /* if both are bit variables */
4286 if (AOP_TYPE (left) == AOP_CRY &&
4287 AOP_TYPE (right) == AOP_CRY)
4289 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4290 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4295 tlbl = newiTempLabel (NULL);
4297 emitcode ("jnz", "%05d$", tlbl->key + 100);
4299 emitcode ("", "%05d$:", tlbl->key + 100);
4303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4304 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4305 freeAsmop (result, NULL, ic, TRUE);
4308 /*-----------------------------------------------------------------*/
4309 /* isLiteralBit - test if lit == 2^n */
4310 /*-----------------------------------------------------------------*/
4312 isLiteralBit (unsigned long lit)
4314 unsigned long pw[32] =
4315 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4316 0x100L, 0x200L, 0x400L, 0x800L,
4317 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4318 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4319 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4320 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4321 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4324 for (idx = 0; idx < 32; idx++)
4330 /*-----------------------------------------------------------------*/
4331 /* continueIfTrue - */
4332 /*-----------------------------------------------------------------*/
4334 continueIfTrue (iCode * ic)
4337 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4341 /*-----------------------------------------------------------------*/
4343 /*-----------------------------------------------------------------*/
4345 jumpIfTrue (iCode * ic)
4348 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4352 /*-----------------------------------------------------------------*/
4353 /* jmpTrueOrFalse - */
4354 /*-----------------------------------------------------------------*/
4356 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4358 // ugly but optimized by peephole
4361 symbol *nlbl = newiTempLabel (NULL);
4362 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4363 emitcode ("", "%05d$:", tlbl->key + 100);
4364 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4365 emitcode ("", "%05d$:", nlbl->key + 100);
4369 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4370 emitcode ("", "%05d$:", tlbl->key + 100);
4375 /*-----------------------------------------------------------------*/
4376 /* genAnd - code for and */
4377 /*-----------------------------------------------------------------*/
4379 genAnd (iCode * ic, iCode * ifx)
4381 operand *left, *right, *result;
4382 int size, offset = 0;
4383 unsigned long lit = 0L;
4387 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4388 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4389 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4392 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4394 AOP_TYPE (left), AOP_TYPE (right));
4395 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4397 AOP_SIZE (left), AOP_SIZE (right));
4400 /* if left is a literal & right is not then exchange them */
4401 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4402 AOP_NEEDSACC (left))
4404 operand *tmp = right;
4409 /* if result = right then exchange them */
4410 if (sameRegs (AOP (result), AOP (right)))
4412 operand *tmp = right;
4417 /* if right is bit then exchange them */
4418 if (AOP_TYPE (right) == AOP_CRY &&
4419 AOP_TYPE (left) != AOP_CRY)
4421 operand *tmp = right;
4425 if (AOP_TYPE (right) == AOP_LIT)
4426 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4428 size = AOP_SIZE (result);
4431 // result = bit & yy;
4432 if (AOP_TYPE (left) == AOP_CRY)
4434 // c = bit & literal;
4435 if (AOP_TYPE (right) == AOP_LIT)
4439 if (size && sameRegs (AOP (result), AOP (left)))
4442 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4447 if (size && (AOP_TYPE (result) == AOP_CRY))
4449 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4452 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4457 emitcode ("clr", "c");
4462 if (AOP_TYPE (right) == AOP_CRY)
4465 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4466 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4471 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4473 emitcode ("rrc", "a");
4474 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4482 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4483 genIfxJump (ifx, "c");
4487 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4488 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4489 if ((AOP_TYPE (right) == AOP_LIT) &&
4490 (AOP_TYPE (result) == AOP_CRY) &&
4491 (AOP_TYPE (left) != AOP_CRY))
4493 int posbit = isLiteralBit (lit);
4498 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4501 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4507 sprintf (buffer, "acc.%d", posbit & 0x07);
4508 genIfxJump (ifx, buffer);
4515 symbol *tlbl = newiTempLabel (NULL);
4516 int sizel = AOP_SIZE (left);
4518 emitcode ("setb", "c");
4521 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4523 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4525 if ((posbit = isLiteralBit (bytelit)) != 0)
4526 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4529 if (bytelit != 0x0FFL)
4530 emitcode ("anl", "a,%s",
4531 aopGet (AOP (right), offset, FALSE, TRUE));
4532 emitcode ("jnz", "%05d$", tlbl->key + 100);
4537 // bit = left & literal
4540 emitcode ("clr", "c");
4541 emitcode ("", "%05d$:", tlbl->key + 100);
4543 // if(left & literal)
4547 jmpTrueOrFalse (ifx, tlbl);
4555 /* if left is same as result */
4556 if (sameRegs (AOP (result), AOP (left)))
4558 for (; size--; offset++)
4560 if (AOP_TYPE (right) == AOP_LIT)
4562 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4564 else if (bytelit == 0)
4565 aopPut (AOP (result), zero, offset);
4566 else if (IS_AOP_PREG (result))
4568 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4569 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4570 aopPut (AOP (result), "a", offset);
4573 emitcode ("anl", "%s,%s",
4574 aopGet (AOP (left), offset, FALSE, TRUE),
4575 aopGet (AOP (right), offset, FALSE, FALSE));
4579 if (AOP_TYPE (left) == AOP_ACC)
4580 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4583 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4584 if (IS_AOP_PREG (result))
4586 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4587 aopPut (AOP (result), "a", offset);
4591 emitcode ("anl", "%s,a",
4592 aopGet (AOP (left), offset, FALSE, TRUE));
4599 // left & result in different registers
4600 if (AOP_TYPE (result) == AOP_CRY)
4603 // if(size), result in bit
4604 // if(!size && ifx), conditional oper: if(left & right)
4605 symbol *tlbl = newiTempLabel (NULL);
4606 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4608 emitcode ("setb", "c");
4611 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4612 emitcode ("anl", "a,%s",
4613 aopGet (AOP (right), offset, FALSE, FALSE));
4615 if (AOP_TYPE(left)==AOP_ACC) {
4616 emitcode("mov", "b,a");
4617 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4618 emitcode("anl", "a,b");
4620 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4621 emitcode ("anl", "a,%s",
4622 aopGet (AOP (left), offset, FALSE, FALSE));
4625 emitcode ("jnz", "%05d$", tlbl->key + 100);
4631 emitcode ("", "%05d$:", tlbl->key + 100);
4635 jmpTrueOrFalse (ifx, tlbl);
4639 for (; (size--); offset++)
4642 // result = left & right
4643 if (AOP_TYPE (right) == AOP_LIT)
4645 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4647 aopPut (AOP (result),
4648 aopGet (AOP (left), offset, FALSE, FALSE),
4652 else if (bytelit == 0)
4654 aopPut (AOP (result), zero, offset);
4658 // faster than result <- left, anl result,right
4659 // and better if result is SFR
4660 if (AOP_TYPE (left) == AOP_ACC)
4661 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4665 emitcode ("anl", "a,%s",
4666 aopGet (AOP (left), offset, FALSE, FALSE));
4668 aopPut (AOP (result), "a", offset);
4674 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4675 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4676 freeAsmop (result, NULL, ic, TRUE);
4679 /*-----------------------------------------------------------------*/
4680 /* genOr - code for or */
4681 /*-----------------------------------------------------------------*/
4683 genOr (iCode * ic, iCode * ifx)
4685 operand *left, *right, *result;
4686 int size, offset = 0;
4687 unsigned long lit = 0L;
4689 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4690 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4691 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4694 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4696 AOP_TYPE (left), AOP_TYPE (right));
4697 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4699 AOP_SIZE (left), AOP_SIZE (right));
4702 /* if left is a literal & right is not then exchange them */
4703 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4704 AOP_NEEDSACC (left))
4706 operand *tmp = right;
4711 /* if result = right then exchange them */
4712 if (sameRegs (AOP (result), AOP (right)))
4714 operand *tmp = right;
4719 /* if right is bit then exchange them */
4720 if (AOP_TYPE (right) == AOP_CRY &&
4721 AOP_TYPE (left) != AOP_CRY)
4723 operand *tmp = right;
4727 if (AOP_TYPE (right) == AOP_LIT)
4728 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4730 size = AOP_SIZE (result);
4734 if (AOP_TYPE (left) == AOP_CRY)
4736 if (AOP_TYPE (right) == AOP_LIT)
4738 // c = bit & literal;
4741 // lit != 0 => result = 1
4742 if (AOP_TYPE (result) == AOP_CRY)
4745 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4747 continueIfTrue (ifx);
4750 emitcode ("setb", "c");
4754 // lit == 0 => result = left
4755 if (size && sameRegs (AOP (result), AOP (left)))
4757 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4762 if (AOP_TYPE (right) == AOP_CRY)
4765 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4766 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4771 symbol *tlbl = newiTempLabel (NULL);
4772 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4773 emitcode ("setb", "c");
4774 emitcode ("jb", "%s,%05d$",
4775 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4777 emitcode ("jnz", "%05d$", tlbl->key + 100);
4778 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4780 jmpTrueOrFalse (ifx, tlbl);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4795 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4796 genIfxJump (ifx, "c");
4800 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4801 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4802 if ((AOP_TYPE (right) == AOP_LIT) &&
4803 (AOP_TYPE (result) == AOP_CRY) &&
4804 (AOP_TYPE (left) != AOP_CRY))
4810 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4812 continueIfTrue (ifx);
4817 // lit = 0, result = boolean(left)
4819 emitcode ("setb", "c");
4823 symbol *tlbl = newiTempLabel (NULL);
4824 emitcode ("jnz", "%05d$", tlbl->key + 100);
4826 emitcode ("", "%05d$:", tlbl->key + 100);
4830 genIfxJump (ifx, "a");
4838 /* if left is same as result */
4839 if (sameRegs (AOP (result), AOP (left)))
4841 for (; size--; offset++)
4843 if (AOP_TYPE (right) == AOP_LIT)
4845 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4847 else if (IS_AOP_PREG (left))
4849 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4850 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4851 aopPut (AOP (result), "a", offset);
4854 emitcode ("orl", "%s,%s",
4855 aopGet (AOP (left), offset, FALSE, TRUE),
4856 aopGet (AOP (right), offset, FALSE, FALSE));
4860 if (AOP_TYPE (left) == AOP_ACC)
4861 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4864 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4865 if (IS_AOP_PREG (left))
4867 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4868 aopPut (AOP (result), "a", offset);
4871 emitcode ("orl", "%s,a",
4872 aopGet (AOP (left), offset, FALSE, TRUE));
4879 // left & result in different registers
4880 if (AOP_TYPE (result) == AOP_CRY)
4883 // if(size), result in bit
4884 // if(!size && ifx), conditional oper: if(left | right)
4885 symbol *tlbl = newiTempLabel (NULL);
4886 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4888 emitcode ("setb", "c");
4891 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4892 emitcode ("orl", "a,%s",
4893 aopGet (AOP (right), offset, FALSE, FALSE));
4895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4896 emitcode ("orl", "a,%s",
4897 aopGet (AOP (left), offset, FALSE, FALSE));
4899 emitcode ("jnz", "%05d$", tlbl->key + 100);
4905 emitcode ("", "%05d$:", tlbl->key + 100);
4909 jmpTrueOrFalse (ifx, tlbl);
4912 for (; (size--); offset++)
4915 // result = left & right
4916 if (AOP_TYPE (right) == AOP_LIT)
4918 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4920 aopPut (AOP (result),
4921 aopGet (AOP (left), offset, FALSE, FALSE),
4926 // faster than result <- left, anl result,right
4927 // and better if result is SFR
4928 if (AOP_TYPE (left) == AOP_ACC)
4929 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4933 emitcode ("orl", "a,%s",
4934 aopGet (AOP (left), offset, FALSE, FALSE));
4936 aopPut (AOP (result), "a", offset);
4941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genXor - code for xclusive or */
4948 /*-----------------------------------------------------------------*/
4950 genXor (iCode * ic, iCode * ifx)
4952 operand *left, *right, *result;
4953 int size, offset = 0;
4954 unsigned long lit = 0L;
4956 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4957 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4958 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4961 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4963 AOP_TYPE (left), AOP_TYPE (right));
4964 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4966 AOP_SIZE (left), AOP_SIZE (right));
4969 /* if left is a literal & right is not ||
4970 if left needs acc & right does not */
4971 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4972 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4974 operand *tmp = right;
4979 /* if result = right then exchange them */
4980 if (sameRegs (AOP (result), AOP (right)))
4982 operand *tmp = right;
4987 /* if right is bit then exchange them */
4988 if (AOP_TYPE (right) == AOP_CRY &&
4989 AOP_TYPE (left) != AOP_CRY)
4991 operand *tmp = right;
4995 if (AOP_TYPE (right) == AOP_LIT)
4996 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4998 size = AOP_SIZE (result);
5002 if (AOP_TYPE (left) == AOP_CRY)
5004 if (AOP_TYPE (right) == AOP_LIT)
5006 // c = bit & literal;
5009 // lit>>1 != 0 => result = 1
5010 if (AOP_TYPE (result) == AOP_CRY)
5013 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5015 continueIfTrue (ifx);
5018 emitcode ("setb", "c");
5025 // lit == 0, result = left
5026 if (size && sameRegs (AOP (result), AOP (left)))
5028 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5032 // lit == 1, result = not(left)
5033 if (size && sameRegs (AOP (result), AOP (left)))
5035 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5041 emitcode ("cpl", "c");
5050 symbol *tlbl = newiTempLabel (NULL);
5051 if (AOP_TYPE (right) == AOP_CRY)
5054 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5058 int sizer = AOP_SIZE (right);
5060 // if val>>1 != 0, result = 1
5061 emitcode ("setb", "c");
5064 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5066 // test the msb of the lsb
5067 emitcode ("anl", "a,#0xfe");
5068 emitcode ("jnz", "%05d$", tlbl->key + 100);
5072 emitcode ("rrc", "a");
5074 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5075 emitcode ("cpl", "c");
5076 emitcode ("", "%05d$:", (tlbl->key + 100));
5083 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5084 genIfxJump (ifx, "c");
5088 if (sameRegs (AOP (result), AOP (left)))
5090 /* if left is same as result */
5091 for (; size--; offset++)
5093 if (AOP_TYPE (right) == AOP_LIT)
5095 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5097 else if (IS_AOP_PREG (left))
5099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5100 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5101 aopPut (AOP (result), "a", offset);
5104 emitcode ("xrl", "%s,%s",
5105 aopGet (AOP (left), offset, FALSE, TRUE),
5106 aopGet (AOP (right), offset, FALSE, FALSE));
5110 if (AOP_TYPE (left) == AOP_ACC)
5111 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5115 if (IS_AOP_PREG (left))
5117 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5118 aopPut (AOP (result), "a", offset);
5121 emitcode ("xrl", "%s,a",
5122 aopGet (AOP (left), offset, FALSE, TRUE));
5129 // left & result in different registers
5130 if (AOP_TYPE (result) == AOP_CRY)
5133 // if(size), result in bit
5134 // if(!size && ifx), conditional oper: if(left ^ right)
5135 symbol *tlbl = newiTempLabel (NULL);
5136 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5138 emitcode ("setb", "c");
5141 if ((AOP_TYPE (right) == AOP_LIT) &&
5142 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5144 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5148 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5149 emitcode ("xrl", "a,%s",
5150 aopGet (AOP (right), offset, FALSE, FALSE));
5152 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5153 emitcode ("xrl", "a,%s",
5154 aopGet (AOP (left), offset, FALSE, FALSE));
5157 emitcode ("jnz", "%05d$", tlbl->key + 100);
5163 emitcode ("", "%05d$:", tlbl->key + 100);
5167 jmpTrueOrFalse (ifx, tlbl);
5170 for (; (size--); offset++)
5173 // result = left & right
5174 if (AOP_TYPE (right) == AOP_LIT)
5176 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5178 aopPut (AOP (result),
5179 aopGet (AOP (left), offset, FALSE, FALSE),
5184 // faster than result <- left, anl result,right
5185 // and better if result is SFR
5186 if (AOP_TYPE (left) == AOP_ACC)
5187 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5190 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5191 emitcode ("xrl", "a,%s",
5192 aopGet (AOP (left), offset, FALSE, TRUE));
5194 aopPut (AOP (result), "a", offset);
5199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (result, NULL, ic, TRUE);
5204 /*-----------------------------------------------------------------*/
5205 /* genInline - write the inline code out */
5206 /*-----------------------------------------------------------------*/
5208 genInline (iCode * ic)
5210 char *buffer, *bp, *bp1;
5212 _G.inLine += (!options.asmpeep);
5214 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5215 strcpy (buffer, IC_INLINE (ic));
5217 /* emit each line as a code */
5242 /* emitcode("",buffer); */
5243 _G.inLine -= (!options.asmpeep);
5246 /*-----------------------------------------------------------------*/
5247 /* genRRC - rotate right with carry */
5248 /*-----------------------------------------------------------------*/
5252 operand *left, *result;
5253 int size, offset = 0;
5256 /* rotate right with carry */
5257 left = IC_LEFT (ic);
5258 result = IC_RESULT (ic);
5259 aopOp (left, ic, FALSE);
5260 aopOp (result, ic, FALSE);
5262 /* move it to the result */
5263 size = AOP_SIZE (result);
5265 if (size == 1) { /* special case for 1 byte */
5266 l = aopGet (AOP (left), offset, FALSE, FALSE);
5268 emitcode ("rr", "a");
5274 l = aopGet (AOP (left), offset, FALSE, FALSE);
5276 emitcode ("rrc", "a");
5277 if (AOP_SIZE (result) > 1)
5278 aopPut (AOP (result), "a", offset--);
5280 /* now we need to put the carry into the
5281 highest order byte of the result */
5282 if (AOP_SIZE (result) > 1)
5284 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5287 emitcode ("mov", "acc.7,c");
5289 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5290 freeAsmop (left, NULL, ic, TRUE);
5291 freeAsmop (result, NULL, ic, TRUE);
5294 /*-----------------------------------------------------------------*/
5295 /* genRLC - generate code for rotate left with carry */
5296 /*-----------------------------------------------------------------*/
5300 operand *left, *result;
5301 int size, offset = 0;
5304 /* rotate right with carry */
5305 left = IC_LEFT (ic);
5306 result = IC_RESULT (ic);
5307 aopOp (left, ic, FALSE);
5308 aopOp (result, ic, FALSE);
5310 /* move it to the result */
5311 size = AOP_SIZE (result);
5315 l = aopGet (AOP (left), offset, FALSE, FALSE);
5317 if (size == 0) { /* special case for 1 byte */
5321 emitcode ("add", "a,acc");
5322 if (AOP_SIZE (result) > 1)
5323 aopPut (AOP (result), "a", offset++);
5326 l = aopGet (AOP (left), offset, FALSE, FALSE);
5328 emitcode ("rlc", "a");
5329 if (AOP_SIZE (result) > 1)
5330 aopPut (AOP (result), "a", offset++);
5333 /* now we need to put the carry into the
5334 highest order byte of the result */
5335 if (AOP_SIZE (result) > 1)
5337 l = aopGet (AOP (result), 0, FALSE, FALSE);
5340 emitcode ("mov", "acc.0,c");
5342 aopPut (AOP (result), "a", 0);
5343 freeAsmop (left, NULL, ic, TRUE);
5344 freeAsmop (result, NULL, ic, TRUE);
5347 /*-----------------------------------------------------------------*/
5348 /* genGetHbit - generates code get highest order bit */
5349 /*-----------------------------------------------------------------*/
5351 genGetHbit (iCode * ic)
5353 operand *left, *result;
5354 left = IC_LEFT (ic);
5355 result = IC_RESULT (ic);
5356 aopOp (left, ic, FALSE);
5357 aopOp (result, ic, FALSE);
5359 /* get the highest order byte into a */
5360 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5361 if (AOP_TYPE (result) == AOP_CRY)
5363 emitcode ("rlc", "a");
5368 emitcode ("rl", "a");
5369 emitcode ("anl", "a,#0x01");
5374 freeAsmop (left, NULL, ic, TRUE);
5375 freeAsmop (result, NULL, ic, TRUE);
5378 /*-----------------------------------------------------------------*/
5379 /* AccRol - rotate left accumulator by known count */
5380 /*-----------------------------------------------------------------*/
5382 AccRol (int shCount)
5384 shCount &= 0x0007; // shCount : 0..7
5391 emitcode ("rl", "a");
5394 emitcode ("rl", "a");
5395 emitcode ("rl", "a");
5398 emitcode ("swap", "a");
5399 emitcode ("rr", "a");
5402 emitcode ("swap", "a");
5405 emitcode ("swap", "a");
5406 emitcode ("rl", "a");
5409 emitcode ("rr", "a");
5410 emitcode ("rr", "a");
5413 emitcode ("rr", "a");
5418 /*-----------------------------------------------------------------*/
5419 /* AccLsh - left shift accumulator by known count */
5420 /*-----------------------------------------------------------------*/
5422 AccLsh (int shCount)
5427 emitcode ("add", "a,acc");
5428 else if (shCount == 2)
5430 emitcode ("add", "a,acc");
5431 emitcode ("add", "a,acc");
5435 /* rotate left accumulator */
5437 /* and kill the lower order bits */
5438 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5443 /*-----------------------------------------------------------------*/
5444 /* AccRsh - right shift accumulator by known count */
5445 /*-----------------------------------------------------------------*/
5447 AccRsh (int shCount)
5454 emitcode ("rrc", "a");
5458 /* rotate right accumulator */
5459 AccRol (8 - shCount);
5460 /* and kill the higher order bits */
5461 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5466 /*-----------------------------------------------------------------*/
5467 /* AccSRsh - signed right shift accumulator by known count */
5468 /*-----------------------------------------------------------------*/
5470 AccSRsh (int shCount)
5477 emitcode ("mov", "c,acc.7");
5478 emitcode ("rrc", "a");
5480 else if (shCount == 2)
5482 emitcode ("mov", "c,acc.7");
5483 emitcode ("rrc", "a");
5484 emitcode ("mov", "c,acc.7");
5485 emitcode ("rrc", "a");
5489 tlbl = newiTempLabel (NULL);
5490 /* rotate right accumulator */
5491 AccRol (8 - shCount);
5492 /* and kill the higher order bits */
5493 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5494 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5495 emitcode ("orl", "a,#0x%02x",
5496 (unsigned char) ~SRMask[shCount]);
5497 emitcode ("", "%05d$:", tlbl->key + 100);
5502 /*-----------------------------------------------------------------*/
5503 /* shiftR1Left2Result - shift right one byte from left to result */
5504 /*-----------------------------------------------------------------*/
5506 shiftR1Left2Result (operand * left, int offl,
5507 operand * result, int offr,
5508 int shCount, int sign)
5510 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5511 /* shift right accumulator */
5516 aopPut (AOP (result), "a", offr);
5519 /*-----------------------------------------------------------------*/
5520 /* shiftL1Left2Result - shift left one byte from left to result */
5521 /*-----------------------------------------------------------------*/
5523 shiftL1Left2Result (operand * left, int offl,
5524 operand * result, int offr, int shCount)
5527 l = aopGet (AOP (left), offl, FALSE, FALSE);
5529 /* shift left accumulator */
5531 aopPut (AOP (result), "a", offr);
5534 /*-----------------------------------------------------------------*/
5535 /* movLeft2Result - move byte from left to result */
5536 /*-----------------------------------------------------------------*/
5538 movLeft2Result (operand * left, int offl,
5539 operand * result, int offr, int sign)
5542 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5544 l = aopGet (AOP (left), offl, FALSE, FALSE);
5546 if (*l == '@' && (IS_AOP_PREG (result)))
5548 emitcode ("mov", "a,%s", l);
5549 aopPut (AOP (result), "a", offr);
5554 aopPut (AOP (result), l, offr);
5557 /* MSB sign in acc.7 ! */
5558 if (getDataSize (left) == offl + 1)
5560 emitcode ("mov", "a,%s", l);
5561 aopPut (AOP (result), "a", offr);
5568 /*-----------------------------------------------------------------*/
5569 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5570 /*-----------------------------------------------------------------*/
5574 emitcode ("rrc", "a");
5575 emitcode ("xch", "a,%s", x);
5576 emitcode ("rrc", "a");
5577 emitcode ("xch", "a,%s", x);
5580 /*-----------------------------------------------------------------*/
5581 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5582 /*-----------------------------------------------------------------*/
5586 emitcode ("xch", "a,%s", x);
5587 emitcode ("rlc", "a");
5588 emitcode ("xch", "a,%s", x);
5589 emitcode ("rlc", "a");
5592 /*-----------------------------------------------------------------*/
5593 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5594 /*-----------------------------------------------------------------*/
5598 emitcode ("xch", "a,%s", x);
5599 emitcode ("add", "a,acc");
5600 emitcode ("xch", "a,%s", x);
5601 emitcode ("rlc", "a");
5604 /*-----------------------------------------------------------------*/
5605 /* AccAXLsh - left shift a:x by known count (0..7) */
5606 /*-----------------------------------------------------------------*/
5608 AccAXLsh (char *x, int shCount)
5623 case 5: // AAAAABBB:CCCCCDDD
5625 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5627 emitcode ("anl", "a,#0x%02x",
5628 SLMask[shCount]); // BBB00000:CCCCCDDD
5630 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5632 AccRol (shCount); // DDDCCCCC:BBB00000
5634 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5636 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5638 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5640 emitcode ("anl", "a,#0x%02x",
5641 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5643 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5645 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5648 case 6: // AAAAAABB:CCCCCCDD
5649 emitcode ("anl", "a,#0x%02x",
5650 SRMask[shCount]); // 000000BB:CCCCCCDD
5651 emitcode ("mov", "c,acc.0"); // c = B
5652 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5654 AccAXRrl1 (x); // BCCCCCCD:D000000B
5655 AccAXRrl1 (x); // BBCCCCCC:DD000000
5657 emitcode("rrc","a");
5658 emitcode("xch","a,%s", x);
5659 emitcode("rrc","a");
5660 emitcode("mov","c,acc.0"); //<< get correct bit
5661 emitcode("xch","a,%s", x);
5663 emitcode("rrc","a");
5664 emitcode("xch","a,%s", x);
5665 emitcode("rrc","a");
5666 emitcode("xch","a,%s", x);
5669 case 7: // a:x <<= 7
5671 emitcode ("anl", "a,#0x%02x",
5672 SRMask[shCount]); // 0000000B:CCCCCCCD
5674 emitcode ("mov", "c,acc.0"); // c = B
5676 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5678 AccAXRrl1 (x); // BCCCCCCC:D0000000
5686 /*-----------------------------------------------------------------*/
5687 /* AccAXRsh - right shift a:x known count (0..7) */
5688 /*-----------------------------------------------------------------*/
5690 AccAXRsh (char *x, int shCount)
5698 AccAXRrl1 (x); // 0->a:x
5703 AccAXRrl1 (x); // 0->a:x
5706 AccAXRrl1 (x); // 0->a:x
5711 case 5: // AAAAABBB:CCCCCDDD = a:x
5713 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5715 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5717 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5719 emitcode ("anl", "a,#0x%02x",
5720 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5722 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5724 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5726 emitcode ("anl", "a,#0x%02x",
5727 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5729 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5731 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5733 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5736 case 6: // AABBBBBB:CCDDDDDD
5738 emitcode ("mov", "c,acc.7");
5739 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5741 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5743 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5745 emitcode ("anl", "a,#0x%02x",
5746 SRMask[shCount]); // 000000AA:BBBBBBCC
5749 case 7: // ABBBBBBB:CDDDDDDD
5751 emitcode ("mov", "c,acc.7"); // c = A
5753 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5755 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5757 emitcode ("anl", "a,#0x%02x",
5758 SRMask[shCount]); // 0000000A:BBBBBBBC
5766 /*-----------------------------------------------------------------*/
5767 /* AccAXRshS - right shift signed a:x known count (0..7) */
5768 /*-----------------------------------------------------------------*/
5770 AccAXRshS (char *x, int shCount)
5778 emitcode ("mov", "c,acc.7");
5779 AccAXRrl1 (x); // s->a:x
5783 emitcode ("mov", "c,acc.7");
5784 AccAXRrl1 (x); // s->a:x
5786 emitcode ("mov", "c,acc.7");
5787 AccAXRrl1 (x); // s->a:x
5792 case 5: // AAAAABBB:CCCCCDDD = a:x
5794 tlbl = newiTempLabel (NULL);
5795 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5797 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5799 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5801 emitcode ("anl", "a,#0x%02x",
5802 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5804 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5806 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5808 emitcode ("anl", "a,#0x%02x",
5809 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5811 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5813 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5815 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5817 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5818 emitcode ("orl", "a,#0x%02x",
5819 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5821 emitcode ("", "%05d$:", tlbl->key + 100);
5822 break; // SSSSAAAA:BBBCCCCC
5824 case 6: // AABBBBBB:CCDDDDDD
5826 tlbl = newiTempLabel (NULL);
5827 emitcode ("mov", "c,acc.7");
5828 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5830 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5832 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5834 emitcode ("anl", "a,#0x%02x",
5835 SRMask[shCount]); // 000000AA:BBBBBBCC
5837 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5838 emitcode ("orl", "a,#0x%02x",
5839 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5841 emitcode ("", "%05d$:", tlbl->key + 100);
5843 case 7: // ABBBBBBB:CDDDDDDD
5845 tlbl = newiTempLabel (NULL);
5846 emitcode ("mov", "c,acc.7"); // c = A
5848 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5850 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5852 emitcode ("anl", "a,#0x%02x",
5853 SRMask[shCount]); // 0000000A:BBBBBBBC
5855 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5856 emitcode ("orl", "a,#0x%02x",
5857 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5859 emitcode ("", "%05d$:", tlbl->key + 100);
5866 /*-----------------------------------------------------------------*/
5867 /* shiftL2Left2Result - shift left two bytes from left to result */
5868 /*-----------------------------------------------------------------*/
5870 shiftL2Left2Result (operand * left, int offl,
5871 operand * result, int offr, int shCount)
5873 if (sameRegs (AOP (result), AOP (left)) &&
5874 ((offl + MSB16) == offr))
5876 /* don't crash result[offr] */
5877 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5878 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5882 movLeft2Result (left, offl, result, offr, 0);
5883 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5885 /* ax << shCount (x = lsb(result)) */
5886 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5887 aopPut (AOP (result), "a", offr + MSB16);
5891 /*-----------------------------------------------------------------*/
5892 /* shiftR2Left2Result - shift right two bytes from left to result */
5893 /*-----------------------------------------------------------------*/
5895 shiftR2Left2Result (operand * left, int offl,
5896 operand * result, int offr,
5897 int shCount, int sign)
5899 if (sameRegs (AOP (result), AOP (left)) &&
5900 ((offl + MSB16) == offr))
5902 /* don't crash result[offr] */
5903 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5904 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5908 movLeft2Result (left, offl, result, offr, 0);
5909 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5911 /* a:x >> shCount (x = lsb(result)) */
5913 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5915 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5916 if (getDataSize (result) > 1)
5917 aopPut (AOP (result), "a", offr + MSB16);
5920 /*-----------------------------------------------------------------*/
5921 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5922 /*-----------------------------------------------------------------*/
5924 shiftLLeftOrResult (operand * left, int offl,
5925 operand * result, int offr, int shCount)
5927 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5928 /* shift left accumulator */
5930 /* or with result */
5931 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5932 /* back to result */
5933 aopPut (AOP (result), "a", offr);
5936 /*-----------------------------------------------------------------*/
5937 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5938 /*-----------------------------------------------------------------*/
5940 shiftRLeftOrResult (operand * left, int offl,
5941 operand * result, int offr, int shCount)
5943 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5944 /* shift right accumulator */
5946 /* or with result */
5947 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5948 /* back to result */
5949 aopPut (AOP (result), "a", offr);
5952 /*-----------------------------------------------------------------*/
5953 /* genlshOne - left shift a one byte quantity by known count */
5954 /*-----------------------------------------------------------------*/
5956 genlshOne (operand * result, operand * left, int shCount)
5958 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5961 /*-----------------------------------------------------------------*/
5962 /* genlshTwo - left shift two bytes by known amount != 0 */
5963 /*-----------------------------------------------------------------*/
5965 genlshTwo (operand * result, operand * left, int shCount)
5969 size = getDataSize (result);
5971 /* if shCount >= 8 */
5979 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5981 movLeft2Result (left, LSB, result, MSB16, 0);
5983 aopPut (AOP (result), zero, LSB);
5986 /* 1 <= shCount <= 7 */
5990 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5992 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5996 /*-----------------------------------------------------------------*/
5997 /* shiftLLong - shift left one long from left to result */
5998 /* offl = LSB or MSB16 */
5999 /*-----------------------------------------------------------------*/
6001 shiftLLong (operand * left, operand * result, int offr)
6004 int size = AOP_SIZE (result);
6006 if (size >= LSB + offr)
6008 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6010 emitcode ("add", "a,acc");
6011 if (sameRegs (AOP (left), AOP (result)) &&
6012 size >= MSB16 + offr && offr != LSB)
6013 emitcode ("xch", "a,%s",
6014 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6016 aopPut (AOP (result), "a", LSB + offr);
6019 if (size >= MSB16 + offr)
6021 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6023 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6026 emitcode ("rlc", "a");
6027 if (sameRegs (AOP (left), AOP (result)) &&
6028 size >= MSB24 + offr && offr != LSB)
6029 emitcode ("xch", "a,%s",
6030 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6032 aopPut (AOP (result), "a", MSB16 + offr);
6035 if (size >= MSB24 + offr)
6037 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6039 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6042 emitcode ("rlc", "a");
6043 if (sameRegs (AOP (left), AOP (result)) &&
6044 size >= MSB32 + offr && offr != LSB)
6045 emitcode ("xch", "a,%s",
6046 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6048 aopPut (AOP (result), "a", MSB24 + offr);
6051 if (size > MSB32 + offr)
6053 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6055 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6058 emitcode ("rlc", "a");
6059 aopPut (AOP (result), "a", MSB32 + offr);
6062 aopPut (AOP (result), zero, LSB);
6065 /*-----------------------------------------------------------------*/
6066 /* genlshFour - shift four byte by a known amount != 0 */
6067 /*-----------------------------------------------------------------*/
6069 genlshFour (operand * result, operand * left, int shCount)
6073 size = AOP_SIZE (result);
6075 /* if shifting more that 3 bytes */
6080 /* lowest order of left goes to the highest
6081 order of the destination */
6082 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6084 movLeft2Result (left, LSB, result, MSB32, 0);
6085 aopPut (AOP (result), zero, LSB);
6086 aopPut (AOP (result), zero, MSB16);
6087 aopPut (AOP (result), zero, MSB24);
6091 /* more than two bytes */
6092 else if (shCount >= 16)
6094 /* lower order two bytes goes to higher order two bytes */
6096 /* if some more remaining */
6098 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6101 movLeft2Result (left, MSB16, result, MSB32, 0);
6102 movLeft2Result (left, LSB, result, MSB24, 0);
6104 aopPut (AOP (result), zero, MSB16);
6105 aopPut (AOP (result), zero, LSB);
6109 /* if more than 1 byte */
6110 else if (shCount >= 8)
6112 /* lower order three bytes goes to higher order three bytes */
6117 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6119 movLeft2Result (left, LSB, result, MSB16, 0);
6125 movLeft2Result (left, MSB24, result, MSB32, 0);
6126 movLeft2Result (left, MSB16, result, MSB24, 0);
6127 movLeft2Result (left, LSB, result, MSB16, 0);
6128 aopPut (AOP (result), zero, LSB);
6130 else if (shCount == 1)
6131 shiftLLong (left, result, MSB16);
6134 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6135 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6136 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6137 aopPut (AOP (result), zero, LSB);
6142 /* 1 <= shCount <= 7 */
6143 else if (shCount <= 2)
6145 shiftLLong (left, result, LSB);
6147 shiftLLong (result, result, LSB);
6149 /* 3 <= shCount <= 7, optimize */
6152 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6153 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6154 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6158 /*-----------------------------------------------------------------*/
6159 /* genLeftShiftLiteral - left shifting by known count */
6160 /*-----------------------------------------------------------------*/
6162 genLeftShiftLiteral (operand * left,
6167 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6170 freeAsmop (right, NULL, ic, TRUE);
6172 aopOp (left, ic, FALSE);
6173 aopOp (result, ic, FALSE);
6175 size = getSize (operandType (result));
6178 emitcode ("; shift left ", "result %d, left %d", size,
6182 /* I suppose that the left size >= result size */
6187 movLeft2Result (left, size, result, size, 0);
6191 else if (shCount >= (size * 8))
6193 aopPut (AOP (result), zero, size);
6199 genlshOne (result, left, shCount);
6203 genlshTwo (result, left, shCount);
6207 genlshFour (result, left, shCount);
6210 fprintf(stderr, "*** ack! mystery literal shift!\n");
6214 freeAsmop (left, NULL, ic, TRUE);
6215 freeAsmop (result, NULL, ic, TRUE);
6218 /*-----------------------------------------------------------------*/
6219 /* genLeftShift - generates code for left shifting */
6220 /*-----------------------------------------------------------------*/
6222 genLeftShift (iCode * ic)
6224 operand *left, *right, *result;
6227 symbol *tlbl, *tlbl1;
6229 right = IC_RIGHT (ic);
6230 left = IC_LEFT (ic);
6231 result = IC_RESULT (ic);
6233 aopOp (right, ic, FALSE);
6235 /* if the shift count is known then do it
6236 as efficiently as possible */
6237 if (AOP_TYPE (right) == AOP_LIT)
6239 genLeftShiftLiteral (left, right, result, ic);
6243 /* shift count is unknown then we have to form
6244 a loop get the loop count in B : Note: we take
6245 only the lower order byte since shifting
6246 more that 32 bits make no sense anyway, ( the
6247 largest size of an object can be only 32 bits ) */
6249 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6250 emitcode ("inc", "b");
6251 freeAsmop (right, NULL, ic, TRUE);
6252 aopOp (left, ic, FALSE);
6253 aopOp (result, ic, FALSE);
6255 /* now move the left to the result if they are not the
6257 if (!sameRegs (AOP (left), AOP (result)) &&
6258 AOP_SIZE (result) > 1)
6261 size = AOP_SIZE (result);
6265 l = aopGet (AOP (left), offset, FALSE, TRUE);
6266 if (*l == '@' && (IS_AOP_PREG (result)))
6269 emitcode ("mov", "a,%s", l);
6270 aopPut (AOP (result), "a", offset);
6273 aopPut (AOP (result), l, offset);
6278 tlbl = newiTempLabel (NULL);
6279 size = AOP_SIZE (result);
6281 tlbl1 = newiTempLabel (NULL);
6283 /* if it is only one byte then */
6286 symbol *tlbl1 = newiTempLabel (NULL);
6288 l = aopGet (AOP (left), 0, FALSE, FALSE);
6290 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6291 emitcode ("", "%05d$:", tlbl->key + 100);
6292 emitcode ("add", "a,acc");
6293 emitcode ("", "%05d$:", tlbl1->key + 100);
6294 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6295 aopPut (AOP (result), "a", 0);
6299 reAdjustPreg (AOP (result));
6301 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6302 emitcode ("", "%05d$:", tlbl->key + 100);
6303 l = aopGet (AOP (result), offset, FALSE, FALSE);
6305 emitcode ("add", "a,acc");
6306 aopPut (AOP (result), "a", offset++);
6309 l = aopGet (AOP (result), offset, FALSE, FALSE);
6311 emitcode ("rlc", "a");
6312 aopPut (AOP (result), "a", offset++);
6314 reAdjustPreg (AOP (result));
6316 emitcode ("", "%05d$:", tlbl1->key + 100);
6317 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6319 freeAsmop (left, NULL, ic, TRUE);
6320 freeAsmop (result, NULL, ic, TRUE);
6323 /*-----------------------------------------------------------------*/
6324 /* genrshOne - right shift a one byte quantity by known count */
6325 /*-----------------------------------------------------------------*/
6327 genrshOne (operand * result, operand * left,
6328 int shCount, int sign)
6330 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6333 /*-----------------------------------------------------------------*/
6334 /* genrshTwo - right shift two bytes by known amount != 0 */
6335 /*-----------------------------------------------------------------*/
6337 genrshTwo (operand * result, operand * left,
6338 int shCount, int sign)
6340 /* if shCount >= 8 */
6345 shiftR1Left2Result (left, MSB16, result, LSB,
6348 movLeft2Result (left, MSB16, result, LSB, sign);
6349 addSign (result, MSB16, sign);
6352 /* 1 <= shCount <= 7 */
6354 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6357 /*-----------------------------------------------------------------*/
6358 /* shiftRLong - shift right one long from left to result */
6359 /* offl = LSB or MSB16 */
6360 /*-----------------------------------------------------------------*/
6362 shiftRLong (operand * left, int offl,
6363 operand * result, int sign)
6365 int isSameRegs=sameRegs(AOP(left),AOP(result));
6367 if (isSameRegs && offl>1) {
6368 // we are in big trouble, but this shouldn't happen
6369 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6372 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6377 emitcode ("rlc", "a");
6378 emitcode ("subb", "a,acc");
6379 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6381 aopPut (AOP(result), zero, MSB32);
6386 emitcode ("clr", "c");
6388 emitcode ("mov", "c,acc.7");
6391 emitcode ("rrc", "a");
6393 if (isSameRegs && offl==MSB16) {
6394 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6396 aopPut (AOP (result), "a", MSB32);
6397 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6400 emitcode ("rrc", "a");
6401 if (isSameRegs && offl==1) {
6402 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6404 aopPut (AOP (result), "a", MSB24);
6405 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6407 emitcode ("rrc", "a");
6408 aopPut (AOP (result), "a", MSB16 - offl);
6412 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6413 emitcode ("rrc", "a");
6414 aopPut (AOP (result), "a", LSB);
6418 /*-----------------------------------------------------------------*/
6419 /* genrshFour - shift four byte by a known amount != 0 */
6420 /*-----------------------------------------------------------------*/
6422 genrshFour (operand * result, operand * left,
6423 int shCount, int sign)
6425 /* if shifting more that 3 bytes */
6430 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6432 movLeft2Result (left, MSB32, result, LSB, sign);
6433 addSign (result, MSB16, sign);
6435 else if (shCount >= 16)
6439 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6442 movLeft2Result (left, MSB24, result, LSB, 0);
6443 movLeft2Result (left, MSB32, result, MSB16, sign);
6445 addSign (result, MSB24, sign);
6447 else if (shCount >= 8)
6451 shiftRLong (left, MSB16, result, sign);
6452 else if (shCount == 0)
6454 movLeft2Result (left, MSB16, result, LSB, 0);
6455 movLeft2Result (left, MSB24, result, MSB16, 0);
6456 movLeft2Result (left, MSB32, result, MSB24, sign);
6457 addSign (result, MSB32, sign);
6461 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6462 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6463 /* the last shift is signed */
6464 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6465 addSign (result, MSB32, sign);
6469 { /* 1 <= shCount <= 7 */
6472 shiftRLong (left, LSB, result, sign);
6474 shiftRLong (result, LSB, result, sign);
6478 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6479 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6480 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6485 /*-----------------------------------------------------------------*/
6486 /* genRightShiftLiteral - right shifting by known count */
6487 /*-----------------------------------------------------------------*/
6489 genRightShiftLiteral (operand * left,
6495 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6498 freeAsmop (right, NULL, ic, TRUE);
6500 aopOp (left, ic, FALSE);
6501 aopOp (result, ic, FALSE);
6504 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6508 size = getDataSize (left);
6509 /* test the LEFT size !!! */
6511 /* I suppose that the left size >= result size */
6514 size = getDataSize (result);
6516 movLeft2Result (left, size, result, size, 0);
6519 else if (shCount >= (size * 8))
6522 /* get sign in acc.7 */
6523 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6524 addSign (result, LSB, sign);
6531 genrshOne (result, left, shCount, sign);
6535 genrshTwo (result, left, shCount, sign);
6539 genrshFour (result, left, shCount, sign);
6545 freeAsmop (left, NULL, ic, TRUE);
6546 freeAsmop (result, NULL, ic, TRUE);
6550 /*-----------------------------------------------------------------*/
6551 /* genSignedRightShift - right shift of signed number */
6552 /*-----------------------------------------------------------------*/
6554 genSignedRightShift (iCode * ic)
6556 operand *right, *left, *result;
6559 symbol *tlbl, *tlbl1;
6561 /* we do it the hard way put the shift count in b
6562 and loop thru preserving the sign */
6564 right = IC_RIGHT (ic);
6565 left = IC_LEFT (ic);
6566 result = IC_RESULT (ic);
6568 aopOp (right, ic, FALSE);
6571 if (AOP_TYPE (right) == AOP_LIT)
6573 genRightShiftLiteral (left, right, result, ic, 1);
6576 /* shift count is unknown then we have to form
6577 a loop get the loop count in B : Note: we take
6578 only the lower order byte since shifting
6579 more that 32 bits make no sense anyway, ( the
6580 largest size of an object can be only 32 bits ) */
6582 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6583 emitcode ("inc", "b");
6584 freeAsmop (right, NULL, ic, TRUE);
6585 aopOp (left, ic, FALSE);
6586 aopOp (result, ic, FALSE);
6588 /* now move the left to the result if they are not the
6590 if (!sameRegs (AOP (left), AOP (result)) &&
6591 AOP_SIZE (result) > 1)
6594 size = AOP_SIZE (result);
6598 l = aopGet (AOP (left), offset, FALSE, TRUE);
6599 if (*l == '@' && IS_AOP_PREG (result))
6602 emitcode ("mov", "a,%s", l);
6603 aopPut (AOP (result), "a", offset);
6606 aopPut (AOP (result), l, offset);
6611 /* mov the highest order bit to OVR */
6612 tlbl = newiTempLabel (NULL);
6613 tlbl1 = newiTempLabel (NULL);
6615 size = AOP_SIZE (result);
6617 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6618 emitcode ("rlc", "a");
6619 emitcode ("mov", "ov,c");
6620 /* if it is only one byte then */
6623 l = aopGet (AOP (left), 0, FALSE, FALSE);
6625 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6626 emitcode ("", "%05d$:", tlbl->key + 100);
6627 emitcode ("mov", "c,ov");
6628 emitcode ("rrc", "a");
6629 emitcode ("", "%05d$:", tlbl1->key + 100);
6630 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6631 aopPut (AOP (result), "a", 0);
6635 reAdjustPreg (AOP (result));
6636 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6637 emitcode ("", "%05d$:", tlbl->key + 100);
6638 emitcode ("mov", "c,ov");
6641 l = aopGet (AOP (result), offset, FALSE, FALSE);
6643 emitcode ("rrc", "a");
6644 aopPut (AOP (result), "a", offset--);
6646 reAdjustPreg (AOP (result));
6647 emitcode ("", "%05d$:", tlbl1->key + 100);
6648 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6651 freeAsmop (left, NULL, ic, TRUE);
6652 freeAsmop (result, NULL, ic, TRUE);
6655 /*-----------------------------------------------------------------*/
6656 /* genRightShift - generate code for right shifting */
6657 /*-----------------------------------------------------------------*/
6659 genRightShift (iCode * ic)
6661 operand *right, *left, *result;
6665 symbol *tlbl, *tlbl1;
6667 /* if signed then we do it the hard way preserve the
6668 sign bit moving it inwards */
6669 retype = getSpec (operandType (IC_RESULT (ic)));
6671 if (!SPEC_USIGN (retype))
6673 genSignedRightShift (ic);
6677 /* signed & unsigned types are treated the same : i.e. the
6678 signed is NOT propagated inwards : quoting from the
6679 ANSI - standard : "for E1 >> E2, is equivalent to division
6680 by 2**E2 if unsigned or if it has a non-negative value,
6681 otherwise the result is implementation defined ", MY definition
6682 is that the sign does not get propagated */
6684 right = IC_RIGHT (ic);
6685 left = IC_LEFT (ic);
6686 result = IC_RESULT (ic);
6688 aopOp (right, ic, FALSE);
6690 /* if the shift count is known then do it
6691 as efficiently as possible */
6692 if (AOP_TYPE (right) == AOP_LIT)
6694 genRightShiftLiteral (left, right, result, ic, 0);
6698 /* shift count is unknown then we have to form
6699 a loop get the loop count in B : Note: we take
6700 only the lower order byte since shifting
6701 more that 32 bits make no sense anyway, ( the
6702 largest size of an object can be only 32 bits ) */
6704 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6705 emitcode ("inc", "b");
6706 freeAsmop (right, NULL, ic, TRUE);
6707 aopOp (left, ic, FALSE);
6708 aopOp (result, ic, FALSE);
6710 /* now move the left to the result if they are not the
6712 if (!sameRegs (AOP (left), AOP (result)) &&
6713 AOP_SIZE (result) > 1)
6716 size = AOP_SIZE (result);
6720 l = aopGet (AOP (left), offset, FALSE, TRUE);
6721 if (*l == '@' && IS_AOP_PREG (result))
6724 emitcode ("mov", "a,%s", l);
6725 aopPut (AOP (result), "a", offset);
6728 aopPut (AOP (result), l, offset);
6733 tlbl = newiTempLabel (NULL);
6734 tlbl1 = newiTempLabel (NULL);
6735 size = AOP_SIZE (result);
6738 /* if it is only one byte then */
6741 l = aopGet (AOP (left), 0, FALSE, FALSE);
6743 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6744 emitcode ("", "%05d$:", tlbl->key + 100);
6746 emitcode ("rrc", "a");
6747 emitcode ("", "%05d$:", tlbl1->key + 100);
6748 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6749 aopPut (AOP (result), "a", 0);
6753 reAdjustPreg (AOP (result));
6754 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6755 emitcode ("", "%05d$:", tlbl->key + 100);
6759 l = aopGet (AOP (result), offset, FALSE, FALSE);
6761 emitcode ("rrc", "a");
6762 aopPut (AOP (result), "a", offset--);
6764 reAdjustPreg (AOP (result));
6766 emitcode ("", "%05d$:", tlbl1->key + 100);
6767 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6770 freeAsmop (left, NULL, ic, TRUE);
6771 freeAsmop (result, NULL, ic, TRUE);
6774 /*-----------------------------------------------------------------*/
6775 /* genUnpackBits - generates code for unpacking bits */
6776 /*-----------------------------------------------------------------*/
6778 genUnpackBits (operand * result, char *rname, int ptype)
6786 etype = getSpec (operandType (result));
6787 rsize = getSize (operandType (result));
6788 /* read the first byte */
6794 emitcode ("mov", "a,@%s", rname);
6798 emitcode ("movx", "a,@%s", rname);
6802 emitcode ("movx", "a,@dptr");
6806 emitcode ("clr", "a");
6807 emitcode ("movc", "a,@a+dptr");
6811 emitcode ("lcall", "__gptrget");
6815 rlen = SPEC_BLEN (etype);
6817 /* if we have bitdisplacement then it fits */
6818 /* into this byte completely or if length is */
6819 /* less than a byte */
6820 if ((shCnt = SPEC_BSTR (etype)) ||
6821 (SPEC_BLEN (etype) <= 8))
6824 /* shift right acc */
6827 emitcode ("anl", "a,#0x%02x",
6828 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6829 aopPut (AOP (result), "a", offset++);
6833 /* bit field did not fit in a byte */
6834 aopPut (AOP (result), "a", offset++);
6843 emitcode ("inc", "%s", rname);
6844 emitcode ("mov", "a,@%s", rname);
6848 emitcode ("inc", "%s", rname);
6849 emitcode ("movx", "a,@%s", rname);
6853 emitcode ("inc", "dptr");
6854 emitcode ("movx", "a,@dptr");
6858 emitcode ("clr", "a");
6859 emitcode ("inc", "dptr");
6860 emitcode ("movc", "a,@a+dptr");
6864 emitcode ("inc", "dptr");
6865 emitcode ("lcall", "__gptrget");
6870 /* if we are done */
6874 aopPut (AOP (result), "a", offset++);
6880 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6882 aopPut (AOP (result), "a", offset++);
6890 aopPut (AOP (result), zero, offset++);
6896 /*-----------------------------------------------------------------*/
6897 /* genDataPointerGet - generates code when ptr offset is known */
6898 /*-----------------------------------------------------------------*/
6900 genDataPointerGet (operand * left,
6906 int size, offset = 0;
6907 aopOp (result, ic, TRUE);
6909 /* get the string representation of the name */
6910 l = aopGet (AOP (left), 0, FALSE, TRUE);
6911 size = AOP_SIZE (result);
6915 sprintf (buffer, "(%s + %d)", l + 1, offset);
6917 sprintf (buffer, "%s", l + 1);
6918 aopPut (AOP (result), buffer, offset++);
6921 freeAsmop (left, NULL, ic, TRUE);
6922 freeAsmop (result, NULL, ic, TRUE);
6925 /*-----------------------------------------------------------------*/
6926 /* genNearPointerGet - emitcode for near pointer fetch */
6927 /*-----------------------------------------------------------------*/
6929 genNearPointerGet (operand * left,
6937 sym_link *rtype, *retype;
6938 sym_link *ltype = operandType (left);
6941 rtype = operandType (result);
6942 retype = getSpec (rtype);
6944 aopOp (left, ic, FALSE);
6946 /* if left is rematerialisable and
6947 result is not bit variable type and
6948 the left is pointer to data space i.e
6949 lower 128 bytes of space */
6950 if (AOP_TYPE (left) == AOP_IMMD &&
6951 !IS_BITVAR (retype) &&
6952 DCL_TYPE (ltype) == POINTER)
6954 genDataPointerGet (left, result, ic);
6958 /* if the value is already in a pointer register
6959 then don't need anything more */
6960 if (!AOP_INPREG (AOP (left)))
6962 /* otherwise get a free pointer register */
6964 preg = getFreePtr (ic, &aop, FALSE);
6965 emitcode ("mov", "%s,%s",
6967 aopGet (AOP (left), 0, FALSE, TRUE));
6971 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6973 //aopOp (result, ic, FALSE);
6974 aopOp (result, ic, result?TRUE:FALSE);
6976 /* if bitfield then unpack the bits */
6977 if (IS_BITVAR (retype))
6978 genUnpackBits (result, rname, POINTER);
6981 /* we have can just get the values */
6982 int size = AOP_SIZE (result);
6987 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6990 emitcode ("mov", "a,@%s", rname);
6991 aopPut (AOP (result), "a", offset);
6995 sprintf (buffer, "@%s", rname);
6996 aopPut (AOP (result), buffer, offset);
7000 emitcode ("inc", "%s", rname);
7004 /* now some housekeeping stuff */
7005 if (aop) /* we had to allocate for this iCode */
7007 if (pi) { /* post increment present */
7008 aopPut(AOP ( left ),rname,0);
7010 freeAsmop (NULL, aop, ic, TRUE);
7014 /* we did not allocate which means left
7015 already in a pointer register, then
7016 if size > 0 && this could be used again
7017 we have to point it back to where it
7019 if ((AOP_SIZE (result) > 1 &&
7020 !OP_SYMBOL (left)->remat &&
7021 (OP_SYMBOL (left)->liveTo > ic->seq ||
7025 int size = AOP_SIZE (result) - 1;
7027 emitcode ("dec", "%s", rname);
7032 freeAsmop (left, NULL, ic, TRUE);
7033 freeAsmop (result, NULL, ic, TRUE);
7034 if (pi) pi->generated = 1;
7037 /*-----------------------------------------------------------------*/
7038 /* genPagedPointerGet - emitcode for paged pointer fetch */
7039 /*-----------------------------------------------------------------*/
7041 genPagedPointerGet (operand * left,
7049 sym_link *rtype, *retype;
7051 rtype = operandType (result);
7052 retype = getSpec (rtype);
7054 aopOp (left, ic, FALSE);
7056 /* if the value is already in a pointer register
7057 then don't need anything more */
7058 if (!AOP_INPREG (AOP (left)))
7060 /* otherwise get a free pointer register */
7062 preg = getFreePtr (ic, &aop, FALSE);
7063 emitcode ("mov", "%s,%s",
7065 aopGet (AOP (left), 0, FALSE, TRUE));
7069 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7071 aopOp (result, ic, FALSE);
7073 /* if bitfield then unpack the bits */
7074 if (IS_BITVAR (retype))
7075 genUnpackBits (result, rname, PPOINTER);
7078 /* we have can just get the values */
7079 int size = AOP_SIZE (result);
7085 emitcode ("movx", "a,@%s", rname);
7086 aopPut (AOP (result), "a", offset);
7091 emitcode ("inc", "%s", rname);
7095 /* now some housekeeping stuff */
7096 if (aop) /* we had to allocate for this iCode */
7098 if (pi) aopPut ( AOP (left), rname, 0);
7099 freeAsmop (NULL, aop, ic, TRUE);
7103 /* we did not allocate which means left
7104 already in a pointer register, then
7105 if size > 0 && this could be used again
7106 we have to point it back to where it
7108 if ((AOP_SIZE (result) > 1 &&
7109 !OP_SYMBOL (left)->remat &&
7110 (OP_SYMBOL (left)->liveTo > ic->seq ||
7114 int size = AOP_SIZE (result) - 1;
7116 emitcode ("dec", "%s", rname);
7121 freeAsmop (left, NULL, ic, TRUE);
7122 freeAsmop (result, NULL, ic, TRUE);
7123 if (pi) pi->generated = 1;
7127 /*-----------------------------------------------------------------*/
7128 /* genFarPointerGet - gget value from far space */
7129 /*-----------------------------------------------------------------*/
7131 genFarPointerGet (operand * left,
7132 operand * result, iCode * ic, iCode * pi)
7135 sym_link *retype = getSpec (operandType (result));
7137 aopOp (left, ic, FALSE);
7139 /* if the operand is already in dptr
7140 then we do nothing else we move the value to dptr */
7141 if (AOP_TYPE (left) != AOP_STR)
7143 /* if this is remateriazable */
7144 if (AOP_TYPE (left) == AOP_IMMD)
7145 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7147 { /* we need to get it byte by byte */
7148 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7149 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7152 /* so dptr know contains the address */
7153 aopOp (result, ic, FALSE);
7155 /* if bit then unpack */
7156 if (IS_BITVAR (retype))
7157 genUnpackBits (result, "dptr", FPOINTER);
7160 size = AOP_SIZE (result);
7165 emitcode ("movx", "a,@dptr");
7166 aopPut (AOP (result), "a", offset++);
7168 emitcode ("inc", "dptr");
7172 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7173 aopPut ( AOP (left), "dpl", 0);
7174 aopPut ( AOP (left), "dph", 1);
7177 freeAsmop (left, NULL, ic, TRUE);
7178 freeAsmop (result, NULL, ic, TRUE);
7181 /*-----------------------------------------------------------------*/
7182 /* genCodePointerGet - gget value from code space */
7183 /*-----------------------------------------------------------------*/
7185 genCodePointerGet (operand * left,
7186 operand * result, iCode * ic, iCode *pi)
7189 sym_link *retype = getSpec (operandType (result));
7191 aopOp (left, ic, FALSE);
7193 /* if the operand is already in dptr
7194 then we do nothing else we move the value to dptr */
7195 if (AOP_TYPE (left) != AOP_STR)
7197 /* if this is remateriazable */
7198 if (AOP_TYPE (left) == AOP_IMMD)
7199 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7201 { /* we need to get it byte by byte */
7202 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7203 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7206 /* so dptr know contains the address */
7207 aopOp (result, ic, FALSE);
7209 /* if bit then unpack */
7210 if (IS_BITVAR (retype))
7211 genUnpackBits (result, "dptr", CPOINTER);
7214 size = AOP_SIZE (result);
7219 emitcode ("clr", "a");
7220 emitcode ("movc", "a,@a+dptr");
7221 aopPut (AOP (result), "a", offset++);
7223 emitcode ("inc", "dptr");
7227 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7228 aopPut ( AOP (left), "dpl", 0);
7229 aopPut ( AOP (left), "dph", 1);
7232 freeAsmop (left, NULL, ic, TRUE);
7233 freeAsmop (result, NULL, ic, TRUE);
7236 /*-----------------------------------------------------------------*/
7237 /* genGenPointerGet - gget value from generic pointer space */
7238 /*-----------------------------------------------------------------*/
7240 genGenPointerGet (operand * left,
7241 operand * result, iCode * ic, iCode *pi)
7244 sym_link *retype = getSpec (operandType (result));
7246 aopOp (left, ic, FALSE);
7248 /* if the operand is already in dptr
7249 then we do nothing else we move the value to dptr */
7250 if (AOP_TYPE (left) != AOP_STR)
7252 /* if this is remateriazable */
7253 if (AOP_TYPE (left) == AOP_IMMD)
7255 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7256 emitcode ("mov", "b,#%d", pointerCode (retype));
7259 { /* we need to get it byte by byte */
7260 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7261 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7262 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7265 /* so dptr know contains the address */
7266 aopOp (result, ic, FALSE);
7268 /* if bit then unpack */
7269 if (IS_BITVAR (retype))
7270 genUnpackBits (result, "dptr", GPOINTER);
7273 size = AOP_SIZE (result);
7278 emitcode ("lcall", "__gptrget");
7279 aopPut (AOP (result), "a", offset++);
7281 emitcode ("inc", "dptr");
7285 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7286 aopPut ( AOP (left), "dpl", 0);
7287 aopPut ( AOP (left), "dph", 1);
7290 freeAsmop (left, NULL, ic, TRUE);
7291 freeAsmop (result, NULL, ic, TRUE);
7294 /*-----------------------------------------------------------------*/
7295 /* genPointerGet - generate code for pointer get */
7296 /*-----------------------------------------------------------------*/
7298 genPointerGet (iCode * ic, iCode *pi)
7300 operand *left, *result;
7301 sym_link *type, *etype;
7304 left = IC_LEFT (ic);
7305 result = IC_RESULT (ic);
7307 /* depending on the type of pointer we need to
7308 move it to the correct pointer register */
7309 type = operandType (left);
7310 etype = getSpec (type);
7311 /* if left is of type of pointer then it is simple */
7312 if (IS_PTR (type) && !IS_FUNC (type->next))
7313 p_type = DCL_TYPE (type);
7316 /* we have to go by the storage class */
7317 p_type = PTR_TYPE (SPEC_OCLS (etype));
7320 /* now that we have the pointer type we assign
7321 the pointer values */
7327 genNearPointerGet (left, result, ic, pi);
7331 genPagedPointerGet (left, result, ic, pi);
7335 genFarPointerGet (left, result, ic, pi);
7339 genCodePointerGet (left, result, ic, pi);
7343 genGenPointerGet (left, result, ic, pi);
7349 /*-----------------------------------------------------------------*/
7350 /* genPackBits - generates code for packed bit storage */
7351 /*-----------------------------------------------------------------*/
7353 genPackBits (sym_link * etype,
7355 char *rname, int p_type)
7363 blen = SPEC_BLEN (etype);
7364 bstr = SPEC_BSTR (etype);
7366 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7369 /* if the bit lenth is less than or */
7370 /* it exactly fits a byte then */
7371 if (SPEC_BLEN (etype) <= 8)
7373 shCount = SPEC_BSTR (etype);
7375 /* shift left acc */
7378 if (SPEC_BLEN (etype) < 8)
7379 { /* if smaller than a byte */
7385 emitcode ("mov", "b,a");
7386 emitcode ("mov", "a,@%s", rname);
7390 emitcode ("mov", "b,a");
7391 emitcode ("movx", "a,@dptr");
7395 emitcode ("push", "b");
7396 emitcode ("push", "acc");
7397 emitcode ("lcall", "__gptrget");
7398 emitcode ("pop", "b");
7402 emitcode ("anl", "a,#0x%02x", (unsigned char)
7403 ((unsigned char) (0xFF << (blen + bstr)) |
7404 (unsigned char) (0xFF >> (8 - bstr))));
7405 emitcode ("orl", "a,b");
7406 if (p_type == GPOINTER)
7407 emitcode ("pop", "b");
7414 emitcode ("mov", "@%s,a", rname);
7418 emitcode ("movx", "@dptr,a");
7422 emitcode ("lcall", "__gptrput");
7427 if (SPEC_BLEN (etype) <= 8)
7430 emitcode ("inc", "%s", rname);
7431 rLen = SPEC_BLEN (etype);
7433 /* now generate for lengths greater than one byte */
7437 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7449 emitcode ("mov", "@%s,a", rname);
7452 emitcode ("mov", "@%s,%s", rname, l);
7457 emitcode ("movx", "@dptr,a");
7462 emitcode ("lcall", "__gptrput");
7465 emitcode ("inc", "%s", rname);
7470 /* last last was not complete */
7473 /* save the byte & read byte */
7477 emitcode ("mov", "b,a");
7478 emitcode ("mov", "a,@%s", rname);
7482 emitcode ("mov", "b,a");
7483 emitcode ("movx", "a,@dptr");
7487 emitcode ("push", "b");
7488 emitcode ("push", "acc");
7489 emitcode ("lcall", "__gptrget");
7490 emitcode ("pop", "b");
7494 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7495 emitcode ("orl", "a,b");
7498 if (p_type == GPOINTER)
7499 emitcode ("pop", "b");
7505 emitcode ("mov", "@%s,a", rname);
7509 emitcode ("movx", "@dptr,a");
7513 emitcode ("lcall", "__gptrput");
7517 /*-----------------------------------------------------------------*/
7518 /* genDataPointerSet - remat pointer to data space */
7519 /*-----------------------------------------------------------------*/
7521 genDataPointerSet (operand * right,
7525 int size, offset = 0;
7526 char *l, buffer[256];
7528 aopOp (right, ic, FALSE);
7530 l = aopGet (AOP (result), 0, FALSE, TRUE);
7531 size = AOP_SIZE (right);
7535 sprintf (buffer, "(%s + %d)", l + 1, offset);
7537 sprintf (buffer, "%s", l + 1);
7538 emitcode ("mov", "%s,%s", buffer,
7539 aopGet (AOP (right), offset++, FALSE, FALSE));
7542 freeAsmop (right, NULL, ic, TRUE);
7543 freeAsmop (result, NULL, ic, TRUE);
7546 /*-----------------------------------------------------------------*/
7547 /* genNearPointerSet - emitcode for near pointer put */
7548 /*-----------------------------------------------------------------*/
7550 genNearPointerSet (operand * right,
7558 sym_link *retype, *letype;
7559 sym_link *ptype = operandType (result);
7561 retype = getSpec (operandType (right));
7562 letype = getSpec (ptype);
7563 aopOp (result, ic, FALSE);
7565 /* if the result is rematerializable &
7566 in data space & not a bit variable */
7567 if (AOP_TYPE (result) == AOP_IMMD &&
7568 DCL_TYPE (ptype) == POINTER &&
7569 !IS_BITVAR (retype) &&
7570 !IS_BITVAR (letype))
7572 genDataPointerSet (right, result, ic);
7576 /* if the value is already in a pointer register
7577 then don't need anything more */
7578 if (!AOP_INPREG (AOP (result)))
7580 /* otherwise get a free pointer register */
7582 preg = getFreePtr (ic, &aop, FALSE);
7583 emitcode ("mov", "%s,%s",
7585 aopGet (AOP (result), 0, FALSE, TRUE));
7589 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7591 aopOp (right, ic, FALSE);
7593 /* if bitfield then unpack the bits */
7594 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7595 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7598 /* we have can just get the values */
7599 int size = AOP_SIZE (right);
7604 l = aopGet (AOP (right), offset, FALSE, TRUE);
7608 emitcode ("mov", "@%s,a", rname);
7611 emitcode ("mov", "@%s,%s", rname, l);
7613 emitcode ("inc", "%s", rname);
7618 /* now some housekeeping stuff */
7619 if (aop) /* we had to allocate for this iCode */
7621 if (pi) aopPut (AOP (result),rname,0);
7622 freeAsmop (NULL, aop, ic, TRUE);
7626 /* we did not allocate which means left
7627 already in a pointer register, then
7628 if size > 0 && this could be used again
7629 we have to point it back to where it
7631 if ((AOP_SIZE (right) > 1 &&
7632 !OP_SYMBOL (result)->remat &&
7633 (OP_SYMBOL (result)->liveTo > ic->seq ||
7637 int size = AOP_SIZE (right) - 1;
7639 emitcode ("dec", "%s", rname);
7644 if (pi) pi->generated = 1;
7645 freeAsmop (result, NULL, ic, TRUE);
7646 freeAsmop (right, NULL, ic, TRUE);
7649 /*-----------------------------------------------------------------*/
7650 /* genPagedPointerSet - emitcode for Paged pointer put */
7651 /*-----------------------------------------------------------------*/
7653 genPagedPointerSet (operand * right,
7661 sym_link *retype, *letype;
7663 retype = getSpec (operandType (right));
7664 letype = getSpec (operandType (result));
7666 aopOp (result, ic, FALSE);
7668 /* if the value is already in a pointer register
7669 then don't need anything more */
7670 if (!AOP_INPREG (AOP (result)))
7672 /* otherwise get a free pointer register */
7674 preg = getFreePtr (ic, &aop, FALSE);
7675 emitcode ("mov", "%s,%s",
7677 aopGet (AOP (result), 0, FALSE, TRUE));
7681 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7683 aopOp (right, ic, FALSE);
7685 /* if bitfield then unpack the bits */
7686 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7687 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7690 /* we have can just get the values */
7691 int size = AOP_SIZE (right);
7696 l = aopGet (AOP (right), offset, FALSE, TRUE);
7699 emitcode ("movx", "@%s,a", rname);
7702 emitcode ("inc", "%s", rname);
7708 /* now some housekeeping stuff */
7709 if (aop) /* we had to allocate for this iCode */
7711 if (pi) aopPut (AOP (result),rname,0);
7712 freeAsmop (NULL, aop, ic, TRUE);
7716 /* we did not allocate which means left
7717 already in a pointer register, then
7718 if size > 0 && this could be used again
7719 we have to point it back to where it
7721 if (AOP_SIZE (right) > 1 &&
7722 !OP_SYMBOL (result)->remat &&
7723 (OP_SYMBOL (result)->liveTo > ic->seq ||
7726 int size = AOP_SIZE (right) - 1;
7728 emitcode ("dec", "%s", rname);
7733 if (pi) pi->generated = 1;
7734 freeAsmop (result, NULL, ic, TRUE);
7735 freeAsmop (right, NULL, ic, TRUE);
7740 /*-----------------------------------------------------------------*/
7741 /* genFarPointerSet - set value from far space */
7742 /*-----------------------------------------------------------------*/
7744 genFarPointerSet (operand * right,
7745 operand * result, iCode * ic, iCode * pi)
7748 sym_link *retype = getSpec (operandType (right));
7749 sym_link *letype = getSpec (operandType (result));
7750 aopOp (result, ic, FALSE);
7752 /* if the operand is already in dptr
7753 then we do nothing else we move the value to dptr */
7754 if (AOP_TYPE (result) != AOP_STR)
7756 /* if this is remateriazable */
7757 if (AOP_TYPE (result) == AOP_IMMD)
7758 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7760 { /* we need to get it byte by byte */
7761 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7762 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7765 /* so dptr know contains the address */
7766 aopOp (right, ic, FALSE);
7768 /* if bit then unpack */
7769 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7770 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7773 size = AOP_SIZE (right);
7778 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7780 emitcode ("movx", "@dptr,a");
7782 emitcode ("inc", "dptr");
7785 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7786 aopPut (AOP(result),"dpl",0);
7787 aopPut (AOP(result),"dph",1);
7790 freeAsmop (result, NULL, ic, TRUE);
7791 freeAsmop (right, NULL, ic, TRUE);
7794 /*-----------------------------------------------------------------*/
7795 /* genGenPointerSet - set value from generic pointer space */
7796 /*-----------------------------------------------------------------*/
7798 genGenPointerSet (operand * right,
7799 operand * result, iCode * ic, iCode * pi)
7802 sym_link *retype = getSpec (operandType (right));
7803 sym_link *letype = getSpec (operandType (result));
7805 aopOp (result, ic, FALSE);
7807 /* if the operand is already in dptr
7808 then we do nothing else we move the value to dptr */
7809 if (AOP_TYPE (result) != AOP_STR)
7811 /* if this is remateriazable */
7812 if (AOP_TYPE (result) == AOP_IMMD)
7814 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7815 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7818 { /* we need to get it byte by byte */
7819 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7820 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7821 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7824 /* so dptr know contains the address */
7825 aopOp (right, ic, FALSE);
7827 /* if bit then unpack */
7828 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7829 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7832 size = AOP_SIZE (right);
7837 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7839 emitcode ("lcall", "__gptrput");
7841 emitcode ("inc", "dptr");
7845 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7846 aopPut (AOP(result),"dpl",0);
7847 aopPut (AOP(result),"dph",1);
7850 freeAsmop (result, NULL, ic, TRUE);
7851 freeAsmop (right, NULL, ic, TRUE);
7854 /*-----------------------------------------------------------------*/
7855 /* genPointerSet - stores the value into a pointer location */
7856 /*-----------------------------------------------------------------*/
7858 genPointerSet (iCode * ic, iCode *pi)
7860 operand *right, *result;
7861 sym_link *type, *etype;
7864 right = IC_RIGHT (ic);
7865 result = IC_RESULT (ic);
7867 /* depending on the type of pointer we need to
7868 move it to the correct pointer register */
7869 type = operandType (result);
7870 etype = getSpec (type);
7871 /* if left is of type of pointer then it is simple */
7872 if (IS_PTR (type) && !IS_FUNC (type->next))
7874 p_type = DCL_TYPE (type);
7878 /* we have to go by the storage class */
7879 p_type = PTR_TYPE (SPEC_OCLS (etype));
7882 /* now that we have the pointer type we assign
7883 the pointer values */
7889 genNearPointerSet (right, result, ic, pi);
7893 genPagedPointerSet (right, result, ic, pi);
7897 genFarPointerSet (right, result, ic, pi);
7901 genGenPointerSet (right, result, ic, pi);
7907 /*-----------------------------------------------------------------*/
7908 /* genIfx - generate code for Ifx statement */
7909 /*-----------------------------------------------------------------*/
7911 genIfx (iCode * ic, iCode * popIc)
7913 operand *cond = IC_COND (ic);
7916 aopOp (cond, ic, FALSE);
7918 /* get the value into acc */
7919 if (AOP_TYPE (cond) != AOP_CRY)
7923 /* the result is now in the accumulator */
7924 freeAsmop (cond, NULL, ic, TRUE);
7926 /* if there was something to be popped then do it */
7930 /* if the condition is a bit variable */
7931 if (isbit && IS_ITEMP (cond) &&
7933 genIfxJump (ic, SPIL_LOC (cond)->rname);
7934 else if (isbit && !IS_ITEMP (cond))
7935 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7937 genIfxJump (ic, "a");
7942 /*-----------------------------------------------------------------*/
7943 /* genAddrOf - generates code for address of */
7944 /*-----------------------------------------------------------------*/
7946 genAddrOf (iCode * ic)
7948 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7951 aopOp (IC_RESULT (ic), ic, FALSE);
7953 /* if the operand is on the stack then we
7954 need to get the stack offset of this
7958 /* if it has an offset then we need to compute
7962 emitcode ("mov", "a,_bp");
7963 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7964 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7968 /* we can just move _bp */
7969 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7971 /* fill the result with zero */
7972 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7977 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7983 /* object not on stack then we need the name */
7984 size = AOP_SIZE (IC_RESULT (ic));
7989 char s[SDCC_NAME_MAX];
7991 sprintf (s, "#(%s >> %d)",
7995 sprintf (s, "#%s", sym->rname);
7996 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8000 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8004 /*-----------------------------------------------------------------*/
8005 /* genFarFarAssign - assignment when both are in far space */
8006 /*-----------------------------------------------------------------*/
8008 genFarFarAssign (operand * result, operand * right, iCode * ic)
8010 int size = AOP_SIZE (right);
8013 /* first push the right side on to the stack */
8016 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8018 emitcode ("push", "acc");
8021 freeAsmop (right, NULL, ic, FALSE);
8022 /* now assign DPTR to result */
8023 aopOp (result, ic, FALSE);
8024 size = AOP_SIZE (result);
8027 emitcode ("pop", "acc");
8028 aopPut (AOP (result), "a", --offset);
8030 freeAsmop (result, NULL, ic, FALSE);
8034 /*-----------------------------------------------------------------*/
8035 /* genAssign - generate code for assignment */
8036 /*-----------------------------------------------------------------*/
8038 genAssign (iCode * ic)
8040 operand *result, *right;
8042 unsigned long lit = 0L;
8044 D(emitcode(";","genAssign"));
8046 result = IC_RESULT (ic);
8047 right = IC_RIGHT (ic);
8049 /* if they are the same */
8050 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8053 aopOp (right, ic, FALSE);
8055 /* special case both in far space */
8056 if (AOP_TYPE (right) == AOP_DPTR &&
8057 IS_TRUE_SYMOP (result) &&
8058 isOperandInFarSpace (result))
8061 genFarFarAssign (result, right, ic);
8065 aopOp (result, ic, TRUE);
8067 /* if they are the same registers */
8068 if (sameRegs (AOP (right), AOP (result)))
8071 /* if the result is a bit */
8072 if (AOP_TYPE (result) == AOP_CRY)
8075 /* if the right size is a literal then
8076 we know what the value is */
8077 if (AOP_TYPE (right) == AOP_LIT)
8079 if (((int) operandLitValue (right)))
8080 aopPut (AOP (result), one, 0);
8082 aopPut (AOP (result), zero, 0);
8086 /* the right is also a bit variable */
8087 if (AOP_TYPE (right) == AOP_CRY)
8089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8090 aopPut (AOP (result), "c", 0);
8096 aopPut (AOP (result), "a", 0);
8100 /* bit variables done */
8102 size = AOP_SIZE (result);
8104 if (AOP_TYPE (right) == AOP_LIT)
8105 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8107 (AOP_TYPE (result) != AOP_REG) &&
8108 (AOP_TYPE (right) == AOP_LIT) &&
8109 !IS_FLOAT (operandType (right)) &&
8112 emitcode ("clr", "a");
8115 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8116 aopPut (AOP (result), "a", size);
8118 aopPut (AOP (result),
8119 aopGet (AOP (right), size, FALSE, FALSE),
8127 aopPut (AOP (result),
8128 aopGet (AOP (right), offset, FALSE, FALSE),
8135 freeAsmop (right, NULL, ic, TRUE);
8136 freeAsmop (result, NULL, ic, TRUE);
8139 /*-----------------------------------------------------------------*/
8140 /* genJumpTab - genrates code for jump table */
8141 /*-----------------------------------------------------------------*/
8143 genJumpTab (iCode * ic)
8148 aopOp (IC_JTCOND (ic), ic, FALSE);
8149 /* get the condition into accumulator */
8150 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8152 /* multiply by three */
8153 emitcode ("add", "a,acc");
8154 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8155 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8157 jtab = newiTempLabel (NULL);
8158 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8159 emitcode ("jmp", "@a+dptr");
8160 emitcode ("", "%05d$:", jtab->key + 100);
8161 /* now generate the jump labels */
8162 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8163 jtab = setNextItem (IC_JTLABELS (ic)))
8164 emitcode ("ljmp", "%05d$", jtab->key + 100);
8168 /*-----------------------------------------------------------------*/
8169 /* genCast - gen code for casting */
8170 /*-----------------------------------------------------------------*/
8172 genCast (iCode * ic)
8174 operand *result = IC_RESULT (ic);
8175 sym_link *ctype = operandType (IC_LEFT (ic));
8176 sym_link *rtype = operandType (IC_RIGHT (ic));
8177 operand *right = IC_RIGHT (ic);
8180 D(emitcode(";", "genCast"));
8182 /* if they are equivalent then do nothing */
8183 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8186 aopOp (right, ic, FALSE);
8187 aopOp (result, ic, FALSE);
8189 /* if the result is a bit */
8190 if (AOP_TYPE (result) == AOP_CRY)
8192 /* if the right size is a literal then
8193 we know what the value is */
8194 if (AOP_TYPE (right) == AOP_LIT)
8196 if (((int) operandLitValue (right)))
8197 aopPut (AOP (result), one, 0);
8199 aopPut (AOP (result), zero, 0);
8204 /* the right is also a bit variable */
8205 if (AOP_TYPE (right) == AOP_CRY)
8207 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8208 aopPut (AOP (result), "c", 0);
8214 aopPut (AOP (result), "a", 0);
8218 /* if they are the same size : or less */
8219 if (AOP_SIZE (result) <= AOP_SIZE (right))
8222 /* if they are in the same place */
8223 if (sameRegs (AOP (right), AOP (result)))
8226 /* if they in different places then copy */
8227 size = AOP_SIZE (result);
8231 aopPut (AOP (result),
8232 aopGet (AOP (right), offset, FALSE, FALSE),
8240 /* if the result is of type pointer */
8245 sym_link *type = operandType (right);
8246 sym_link *etype = getSpec (type);
8248 /* pointer to generic pointer */
8249 if (IS_GENPTR (ctype))
8254 p_type = DCL_TYPE (type);
8257 if (SPEC_SCLS(etype)==S_REGISTER) {
8258 // let's assume it is a generic pointer
8261 /* we have to go by the storage class */
8262 p_type = PTR_TYPE (SPEC_OCLS (etype));
8266 /* the first two bytes are known */
8267 size = GPTRSIZE - 1;
8271 aopPut (AOP (result),
8272 aopGet (AOP (right), offset, FALSE, FALSE),
8276 /* the last byte depending on type */
8292 case PPOINTER: // what the fck is this?
8297 /* this should never happen */
8298 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8299 "got unknown pointer type");
8302 aopPut (AOP (result), l, GPTRSIZE - 1);
8306 /* just copy the pointers */
8307 size = AOP_SIZE (result);
8311 aopPut (AOP (result),
8312 aopGet (AOP (right), offset, FALSE, FALSE),
8319 /* so we now know that the size of destination is greater
8320 than the size of the source */
8321 /* we move to result for the size of source */
8322 size = AOP_SIZE (right);
8326 aopPut (AOP (result),
8327 aopGet (AOP (right), offset, FALSE, FALSE),
8332 /* now depending on the sign of the source && destination */
8333 size = AOP_SIZE (result) - AOP_SIZE (right);
8334 /* if unsigned or not an integral type */
8335 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8338 aopPut (AOP (result), zero, offset++);
8342 /* we need to extend the sign :{ */
8343 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8346 emitcode ("rlc", "a");
8347 emitcode ("subb", "a,acc");
8349 aopPut (AOP (result), "a", offset++);
8352 /* we are done hurray !!!! */
8355 freeAsmop (right, NULL, ic, TRUE);
8356 freeAsmop (result, NULL, ic, TRUE);
8360 /*-----------------------------------------------------------------*/
8361 /* genDjnz - generate decrement & jump if not zero instrucion */
8362 /*-----------------------------------------------------------------*/
8364 genDjnz (iCode * ic, iCode * ifx)
8370 /* if the if condition has a false label
8371 then we cannot save */
8375 /* if the minus is not of the form
8377 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8378 !IS_OP_LITERAL (IC_RIGHT (ic)))
8381 if (operandLitValue (IC_RIGHT (ic)) != 1)
8384 /* if the size of this greater than one then no
8386 if (getSize (operandType (IC_RESULT (ic))) > 1)
8389 /* otherwise we can save BIG */
8390 lbl = newiTempLabel (NULL);
8391 lbl1 = newiTempLabel (NULL);
8393 aopOp (IC_RESULT (ic), ic, FALSE);
8395 if (AOP_NEEDSACC(IC_RESULT(ic)))
8397 /* If the result is accessed indirectly via
8398 * the accumulator, we must explicitly write
8399 * it back after the decrement.
8401 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8403 if (strcmp(rByte, "a"))
8405 /* Something is hopelessly wrong */
8406 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8407 __FILE__, __LINE__);
8408 /* We can just give up; the generated code will be inefficient,
8411 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8414 emitcode ("dec", "%s", rByte);
8415 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8416 emitcode ("jnz", "%05d$", lbl->key + 100);
8418 else if (IS_AOP_PREG (IC_RESULT (ic)))
8420 emitcode ("dec", "%s",
8421 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8422 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8423 emitcode ("jnz", "%05d$", lbl->key + 100);
8427 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8430 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8431 emitcode ("", "%05d$:", lbl->key + 100);
8432 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8433 emitcode ("", "%05d$:", lbl1->key + 100);
8435 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8440 /*-----------------------------------------------------------------*/
8441 /* genReceive - generate code for a receive iCode */
8442 /*-----------------------------------------------------------------*/
8444 genReceive (iCode * ic)
8446 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8447 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8448 IS_TRUE_SYMOP (IC_RESULT (ic))))
8451 int size = getSize (operandType (IC_RESULT (ic)));
8452 int offset = fReturnSizeMCS51 - size;
8455 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8456 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8459 aopOp (IC_RESULT (ic), ic, FALSE);
8460 size = AOP_SIZE (IC_RESULT (ic));
8464 emitcode ("pop", "acc");
8465 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8472 aopOp (IC_RESULT (ic), ic, FALSE);
8474 assignResultValue (IC_RESULT (ic));
8477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8480 /*-----------------------------------------------------------------*/
8481 /* gen51Code - generate code for 8051 based controllers */
8482 /*-----------------------------------------------------------------*/
8484 gen51Code (iCode * lic)
8489 lineHead = lineCurr = NULL;
8491 /* print the allocation information */
8493 printAllocInfo (currFunc, codeOutFile);
8494 /* if debug information required */
8495 /* if (options.debug && currFunc) { */
8496 if (options.debug && currFunc)
8498 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8500 if (IS_STATIC (currFunc->etype))
8501 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8503 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8506 /* stack pointer name */
8507 if (options.useXstack)
8513 for (ic = lic; ic; ic = ic->next)
8516 if (cln != ic->lineno)
8521 emitcode ("", "C$%s$%d$%d$%d ==.",
8522 FileBaseName (ic->filename), ic->lineno,
8523 ic->level, ic->block);
8526 emitcode (";", "%s %d", ic->filename, ic->lineno);
8529 /* if the result is marked as
8530 spilt and rematerializable or code for
8531 this has already been generated then
8533 if (resultRemat (ic) || ic->generated)
8536 /* depending on the operation */
8556 /* IPOP happens only when trying to restore a
8557 spilt live range, if there is an ifx statement
8558 following this pop then the if statement might
8559 be using some of the registers being popped which
8560 would destory the contents of the register so
8561 we need to check for this condition and handle it */
8563 ic->next->op == IFX &&
8564 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8565 genIfx (ic->next, ic);
8583 genEndFunction (ic);
8603 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8620 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8624 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8631 /* note these two are xlated by algebraic equivalence
8632 during parsing SDCC.y */
8633 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8634 "got '>=' or '<=' shouldn't have come here");
8638 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8650 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8654 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8658 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8685 case GET_VALUE_AT_ADDRESS:
8686 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8690 if (POINTER_SET (ic))
8691 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8717 addSet (&_G.sendSet, ic);
8726 /* now we are ready to call the
8727 peep hole optimizer */
8728 if (!options.nopeep)
8729 peepHole (&lineHead);
8731 /* now do the actual printing */
8732 printLine (lineHead, codeOutFile);