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__)
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)
276 memmap *space = SPEC_OCLS (sym->etype);
278 /* if already has one */
282 /* assign depending on the storage class */
283 /* if it is on the stack or indirectly addressable */
284 /* space we need to assign either r0 or r1 to it */
285 if (sym->onStack || sym->iaccess)
287 sym->aop = aop = newAsmop (0);
288 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
289 aop->size = getSize (sym->type);
291 /* now assign the address of the variable to
292 the pointer register */
293 if (aop->type != AOP_STK)
299 emitcode ("push", "acc");
301 emitcode ("mov", "a,_bp");
302 emitcode ("add", "a,#0x%02x",
304 ((char) (sym->stack - _G.nRegsSaved)) :
305 ((char) sym->stack)) & 0xff);
306 emitcode ("mov", "%s,a",
307 aop->aopu.aop_ptr->name);
310 emitcode ("pop", "acc");
313 emitcode ("mov", "%s,#%s",
314 aop->aopu.aop_ptr->name,
316 aop->paged = space->paged;
319 aop->aopu.aop_stk = sym->stack;
323 /* if in bit space */
324 if (IN_BITSPACE (space))
326 sym->aop = aop = newAsmop (AOP_CRY);
327 aop->aopu.aop_dir = sym->rname;
328 aop->size = getSize (sym->type);
331 /* if it is in direct space */
332 if (IN_DIRSPACE (space))
334 sym->aop = aop = newAsmop (AOP_DIR);
335 aop->aopu.aop_dir = sym->rname;
336 aop->size = getSize (sym->type);
340 /* special case for a function */
341 if (IS_FUNC (sym->type))
343 sym->aop = aop = newAsmop (AOP_IMMD);
344 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
345 strcpy (aop->aopu.aop_immd, sym->rname);
346 aop->size = FPTRSIZE;
350 /* only remaining is far space */
351 /* in which case DPTR gets the address */
352 sym->aop = aop = newAsmop (AOP_DPTR);
353 emitcode ("mov", "dptr,#%s", sym->rname);
354 aop->size = getSize (sym->type);
356 /* if it is in code space */
357 if (IN_CODESPACE (space))
363 /*-----------------------------------------------------------------*/
364 /* aopForRemat - rematerialzes an object */
365 /*-----------------------------------------------------------------*/
367 aopForRemat (symbol * sym)
369 iCode *ic = sym->rematiCode;
370 asmop *aop = newAsmop (AOP_IMMD);
376 val += (int) operandLitValue (IC_RIGHT (ic));
377 else if (ic->op == '-')
378 val -= (int) operandLitValue (IC_RIGHT (ic));
382 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
386 sprintf (buffer, "(%s %c 0x%04x)",
387 OP_SYMBOL (IC_LEFT (ic))->rname,
388 val >= 0 ? '+' : '-',
391 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
393 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
394 strcpy (aop->aopu.aop_immd, buffer);
398 /*-----------------------------------------------------------------*/
399 /* regsInCommon - two operands have some registers in common */
400 /*-----------------------------------------------------------------*/
402 regsInCommon (operand * op1, operand * op2)
407 /* if they have registers in common */
408 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
411 sym1 = OP_SYMBOL (op1);
412 sym2 = OP_SYMBOL (op2);
414 if (sym1->nRegs == 0 || sym2->nRegs == 0)
417 for (i = 0; i < sym1->nRegs; i++)
423 for (j = 0; j < sym2->nRegs; j++)
428 if (sym2->regs[j] == sym1->regs[i])
436 /*-----------------------------------------------------------------*/
437 /* operandsEqu - equivalent */
438 /*-----------------------------------------------------------------*/
440 operandsEqu (operand * op1, operand * op2)
444 /* if they not symbols */
445 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
448 sym1 = OP_SYMBOL (op1);
449 sym2 = OP_SYMBOL (op2);
451 /* if both are itemps & one is spilt
452 and the other is not then false */
453 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
454 sym1->isspilt != sym2->isspilt)
457 /* if they are the same */
461 if (strcmp (sym1->rname, sym2->rname) == 0)
465 /* if left is a tmp & right is not */
466 if (IS_ITEMP (op1) &&
469 (sym1->usl.spillLoc == sym2))
472 if (IS_ITEMP (op2) &&
476 (sym2->usl.spillLoc == sym1))
482 /*-----------------------------------------------------------------*/
483 /* sameRegs - two asmops have the same registers */
484 /*-----------------------------------------------------------------*/
486 sameRegs (asmop * aop1, asmop * aop2)
493 if (aop1->type != AOP_REG ||
494 aop2->type != AOP_REG)
497 if (aop1->size != aop2->size)
500 for (i = 0; i < aop1->size; i++)
501 if (aop1->aopu.aop_reg[i] !=
502 aop2->aopu.aop_reg[i])
508 /*-----------------------------------------------------------------*/
509 /* aopOp - allocates an asmop for an operand : */
510 /*-----------------------------------------------------------------*/
512 aopOp (operand * op, iCode * ic, bool result)
521 /* if this a literal */
522 if (IS_OP_LITERAL (op))
524 op->aop = aop = newAsmop (AOP_LIT);
525 aop->aopu.aop_lit = op->operand.valOperand;
526 aop->size = getSize (operandType (op));
530 /* if already has a asmop then continue */
534 /* if the underlying symbol has a aop */
535 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
537 op->aop = OP_SYMBOL (op)->aop;
541 /* if this is a true symbol */
542 if (IS_TRUE_SYMOP (op))
544 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
548 /* this is a temporary : this has
554 e) can be a return use only */
556 sym = OP_SYMBOL (op);
559 /* if the type is a conditional */
560 if (sym->regType == REG_CND)
562 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
567 /* if it is spilt then two situations
569 b) has a spill location */
570 if (sym->isspilt || sym->nRegs == 0)
573 /* rematerialize it NOW */
576 sym->aop = op->aop = aop =
578 aop->size = getSize (sym->type);
585 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
586 aop->size = getSize (sym->type);
587 for (i = 0; i < 2; i++)
588 aop->aopu.aop_str[i] = accUse[i];
595 aop = op->aop = sym->aop = newAsmop (AOP_STR);
596 aop->size = getSize (sym->type);
597 for (i = 0; i < fReturnSizeMCS51; i++)
598 aop->aopu.aop_str[i] = fReturn[i];
602 /* else spill location */
603 sym->aop = op->aop = aop =
604 aopForSym (ic, sym->usl.spillLoc, result);
605 aop->size = getSize (sym->type);
609 /* must be in a register */
610 sym->aop = op->aop = aop = newAsmop (AOP_REG);
611 aop->size = sym->nRegs;
612 for (i = 0; i < sym->nRegs; i++)
613 aop->aopu.aop_reg[i] = sym->regs[i];
616 /*-----------------------------------------------------------------*/
617 /* freeAsmop - free up the asmop given to an operand */
618 /*----------------------------------------------------------------*/
620 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
637 /* depending on the asmop type only three cases need work AOP_RO
638 , AOP_R1 && AOP_STK */
646 emitcode ("pop", "ar0");
650 bitVectUnSetBit (ic->rUsed, R0_IDX);
658 emitcode ("pop", "ar1");
662 bitVectUnSetBit (ic->rUsed, R1_IDX);
668 int stk = aop->aopu.aop_stk + aop->size;
669 bitVectUnSetBit (ic->rUsed, R0_IDX);
670 bitVectUnSetBit (ic->rUsed, R1_IDX);
672 getFreePtr (ic, &aop, FALSE);
676 emitcode ("mov", "a,_bp");
677 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
678 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
682 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
687 emitcode ("pop", "acc");
688 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
691 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
694 freeAsmop (op, NULL, ic, TRUE);
697 emitcode ("pop", "ar0");
703 emitcode ("pop", "ar1");
710 /* all other cases just dealloc */
716 OP_SYMBOL (op)->aop = NULL;
717 /* if the symbol has a spill */
719 SPIL_LOC (op)->aop = NULL;
724 /*-----------------------------------------------------------------*/
725 /* aopGet - for fetching value of the aop */
726 /*-----------------------------------------------------------------*/
728 aopGet (asmop * aop, int offset, bool bit16, bool dname)
733 /* offset is greater than
735 if (offset > (aop->size - 1) &&
736 aop->type != AOP_LIT)
739 /* depending on type */
745 /* if we need to increment it */
746 while (offset > aop->coff)
748 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
752 while (offset < aop->coff)
754 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
761 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
762 return (dname ? "acc" : "a");
764 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
765 rs = Safe_calloc (1, strlen (s) + 1);
770 while (offset > aop->coff)
772 emitcode ("inc", "dptr");
776 while (offset < aop->coff)
778 emitcode ("lcall", "__decdptr");
785 emitcode ("clr", "a");
786 emitcode ("movc", "a,@a+dptr");
790 emitcode ("movx", "a,@dptr");
792 return (dname ? "acc" : "a");
797 sprintf (s, "#%s", aop->aopu.aop_immd);
799 sprintf (s, "#(%s >> %d)",
805 rs = Safe_calloc (1, strlen (s) + 1);
811 sprintf (s, "(%s + %d)",
815 sprintf (s, "%s", aop->aopu.aop_dir);
816 rs = Safe_calloc (1, strlen (s) + 1);
822 return aop->aopu.aop_reg[offset]->dname;
824 return aop->aopu.aop_reg[offset]->name;
827 emitcode ("clr", "a");
828 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
829 emitcode ("rlc", "a");
830 return (dname ? "acc" : "a");
833 if (!offset && dname)
835 return aop->aopu.aop_str[offset];
838 return aopLiteral (aop->aopu.aop_lit, offset);
842 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
846 return aop->aopu.aop_str[offset];
850 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
851 "aopget got unsupported aop->type");
854 /*-----------------------------------------------------------------*/
855 /* aopPut - puts a string for a aop */
856 /*-----------------------------------------------------------------*/
858 aopPut (asmop * aop, char *s, int offset)
862 if (aop->size && offset > (aop->size - 1))
864 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
865 "aopPut got offset > aop->size");
869 /* will assign value to value */
870 /* depending on where it is ofcourse */
875 sprintf (d, "(%s + %d)",
876 aop->aopu.aop_dir, offset);
878 sprintf (d, "%s", aop->aopu.aop_dir);
881 emitcode ("mov", "%s,%s", d, s);
886 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
887 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
890 strcmp (s, "r0") == 0 ||
891 strcmp (s, "r1") == 0 ||
892 strcmp (s, "r2") == 0 ||
893 strcmp (s, "r3") == 0 ||
894 strcmp (s, "r4") == 0 ||
895 strcmp (s, "r5") == 0 ||
896 strcmp (s, "r6") == 0 ||
897 strcmp (s, "r7") == 0)
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->dname, s);
901 emitcode ("mov", "%s,%s",
902 aop->aopu.aop_reg[offset]->name, s);
909 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
910 "aopPut writting to code space");
914 while (offset > aop->coff)
917 emitcode ("inc", "dptr");
920 while (offset < aop->coff)
923 emitcode ("lcall", "__decdptr");
928 /* if not in accumulater */
931 emitcode ("movx", "@dptr,a");
936 while (offset > aop->coff)
939 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
941 while (offset < aop->coff)
944 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
957 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
959 else if (strcmp (s, "r0") == 0 ||
960 strcmp (s, "r1") == 0 ||
961 strcmp (s, "r2") == 0 ||
962 strcmp (s, "r3") == 0 ||
963 strcmp (s, "r4") == 0 ||
964 strcmp (s, "r5") == 0 ||
965 strcmp (s, "r6") == 0 ||
966 strcmp (s, "r7") == 0)
969 sprintf (buffer, "a%s", s);
970 emitcode ("mov", "@%s,%s",
971 aop->aopu.aop_ptr->name, buffer);
974 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
979 if (strcmp (s, "a") == 0)
980 emitcode ("push", "acc");
982 emitcode ("push", "%s", s);
987 /* if bit variable */
988 if (!aop->aopu.aop_dir)
990 emitcode ("clr", "a");
991 emitcode ("rlc", "a");
996 emitcode ("clr", "%s", aop->aopu.aop_dir);
998 emitcode ("setb", "%s", aop->aopu.aop_dir);
999 else if (!strcmp (s, "c"))
1000 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1003 if (strcmp (s, "a"))
1008 symbol *lbl = newiTempLabel (NULL);
1009 emitcode ("clr", "c; oops");
1010 emitcode ("jz", "%05d$", lbl->key + 100);
1011 emitcode ("cpl", "c");
1012 emitcode ("", "%05d$:", lbl->key + 100);
1013 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1021 if (strcmp (aop->aopu.aop_str[offset], s))
1022 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1027 if (!offset && (strcmp (s, "acc") == 0))
1030 if (strcmp (aop->aopu.aop_str[offset], s))
1031 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1035 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1036 "aopPut got unsupported aop->type");
1044 /*-----------------------------------------------------------------*/
1045 /* pointToEnd :- points to the last byte of the operand */
1046 /*-----------------------------------------------------------------*/
1048 pointToEnd (asmop * aop)
1054 aop->coff = count = (aop->size - 1);
1060 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1064 emitcode ("inc", "dptr");
1071 /*-----------------------------------------------------------------*/
1072 /* reAdjustPreg - points a register back to where it should */
1073 /*-----------------------------------------------------------------*/
1075 reAdjustPreg (asmop * aop)
1077 if ((aop->coff==0) || aop->size <= 1)
1085 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1090 emitcode ("lcall", "__decdptr");
1097 #define AOP(op) op->aop
1098 #define AOP_TYPE(op) AOP(op)->type
1099 #define AOP_SIZE(op) AOP(op)->size
1100 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1101 AOP_TYPE(x) == AOP_R0))
1103 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1104 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1106 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1107 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1108 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1110 /*-----------------------------------------------------------------*/
1111 /* genNotFloat - generates not for float operations */
1112 /*-----------------------------------------------------------------*/
1114 genNotFloat (operand * op, operand * res)
1120 /* we will put 127 in the first byte of
1122 aopPut (AOP (res), "#127", 0);
1123 size = AOP_SIZE (op) - 1;
1126 l = aopGet (op->aop, offset++, FALSE, FALSE);
1131 emitcode ("orl", "a,%s",
1133 offset++, FALSE, FALSE));
1136 tlbl = newiTempLabel (NULL);
1137 aopPut (res->aop, one, 1);
1138 emitcode ("jz", "%05d$", (tlbl->key + 100));
1139 aopPut (res->aop, zero, 1);
1140 emitcode ("", "%05d$:", (tlbl->key + 100));
1142 size = res->aop->size - 2;
1144 /* put zeros in the rest */
1146 aopPut (res->aop, zero, offset++);
1149 /*-----------------------------------------------------------------*/
1150 /* opIsGptr: returns non-zero if the passed operand is */
1151 /* a generic pointer type. */
1152 /*-----------------------------------------------------------------*/
1154 opIsGptr (operand * op)
1156 sym_link *type = operandType (op);
1158 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1165 /*-----------------------------------------------------------------*/
1166 /* getDataSize - get the operand data size */
1167 /*-----------------------------------------------------------------*/
1169 getDataSize (operand * op)
1172 size = AOP_SIZE (op);
1173 if (size == GPTRSIZE)
1175 sym_link *type = operandType (op);
1176 if (IS_GENPTR (type))
1178 /* generic pointer; arithmetic operations
1179 * should ignore the high byte (pointer type).
1187 /*-----------------------------------------------------------------*/
1188 /* outAcc - output Acc */
1189 /*-----------------------------------------------------------------*/
1191 outAcc (operand * result)
1194 size = getDataSize (result);
1197 aopPut (AOP (result), "a", 0);
1200 /* unsigned or positive */
1203 aopPut (AOP (result), zero, offset++);
1208 /*-----------------------------------------------------------------*/
1209 /* outBitC - output a bit C */
1210 /*-----------------------------------------------------------------*/
1212 outBitC (operand * result)
1214 /* if the result is bit */
1215 if (AOP_TYPE (result) == AOP_CRY)
1216 aopPut (AOP (result), "c", 0);
1219 emitcode ("clr", "a");
1220 emitcode ("rlc", "a");
1225 /*-----------------------------------------------------------------*/
1226 /* toBoolean - emit code for orl a,operator(sizeop) */
1227 /*-----------------------------------------------------------------*/
1229 toBoolean (operand * oper)
1231 int size = AOP_SIZE (oper) - 1;
1233 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1235 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1239 /*-----------------------------------------------------------------*/
1240 /* genNot - generate code for ! operation */
1241 /*-----------------------------------------------------------------*/
1246 sym_link *optype = operandType (IC_LEFT (ic));
1248 /* assign asmOps to operand & result */
1249 aopOp (IC_LEFT (ic), ic, FALSE);
1250 aopOp (IC_RESULT (ic), ic, TRUE);
1252 /* if in bit space then a special case */
1253 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1255 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1256 emitcode ("cpl", "c");
1257 outBitC (IC_RESULT (ic));
1261 /* if type float then do float */
1262 if (IS_FLOAT (optype))
1264 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1268 toBoolean (IC_LEFT (ic));
1270 tlbl = newiTempLabel (NULL);
1271 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1272 emitcode ("", "%05d$:", tlbl->key + 100);
1273 outBitC (IC_RESULT (ic));
1276 /* release the aops */
1277 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1278 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1282 /*-----------------------------------------------------------------*/
1283 /* genCpl - generate code for complement */
1284 /*-----------------------------------------------------------------*/
1292 /* assign asmOps to operand & result */
1293 aopOp (IC_LEFT (ic), ic, FALSE);
1294 aopOp (IC_RESULT (ic), ic, TRUE);
1296 /* if both are in bit space then
1298 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1299 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1302 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1303 emitcode ("cpl", "c");
1304 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1308 size = AOP_SIZE (IC_RESULT (ic));
1311 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1313 emitcode ("cpl", "a");
1314 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1319 /* release the aops */
1320 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1321 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1324 /*-----------------------------------------------------------------*/
1325 /* genUminusFloat - unary minus for floating points */
1326 /*-----------------------------------------------------------------*/
1328 genUminusFloat (operand * op, operand * result)
1330 int size, offset = 0;
1332 /* for this we just need to flip the
1333 first it then copy the rest in place */
1334 size = AOP_SIZE (op) - 1;
1335 l = aopGet (AOP (op), 3, FALSE, FALSE);
1339 emitcode ("cpl", "acc.7");
1340 aopPut (AOP (result), "a", 3);
1344 aopPut (AOP (result),
1345 aopGet (AOP (op), offset, FALSE, FALSE),
1351 /*-----------------------------------------------------------------*/
1352 /* genUminus - unary minus code generation */
1353 /*-----------------------------------------------------------------*/
1355 genUminus (iCode * ic)
1358 sym_link *optype, *rtype;
1362 aopOp (IC_LEFT (ic), ic, FALSE);
1363 aopOp (IC_RESULT (ic), ic, TRUE);
1365 /* if both in bit space then special
1367 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1368 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1371 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1372 emitcode ("cpl", "c");
1373 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1377 optype = operandType (IC_LEFT (ic));
1378 rtype = operandType (IC_RESULT (ic));
1380 /* if float then do float stuff */
1381 if (IS_FLOAT (optype))
1383 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1387 /* otherwise subtract from zero */
1388 size = AOP_SIZE (IC_LEFT (ic));
1393 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1394 if (!strcmp (l, "a"))
1398 emitcode ("cpl", "a");
1399 emitcode ("addc", "a,#0");
1405 emitcode ("clr", "a");
1406 emitcode ("subb", "a,%s", l);
1408 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1411 /* if any remaining bytes in the result */
1412 /* we just need to propagate the sign */
1413 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1415 emitcode ("rlc", "a");
1416 emitcode ("subb", "a,acc");
1418 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1422 /* release the aops */
1423 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1424 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1427 /*-----------------------------------------------------------------*/
1428 /* saveRegisters - will look for a call and save the registers */
1429 /*-----------------------------------------------------------------*/
1431 saveRegisters (iCode * lic)
1439 for (ic = lic; ic; ic = ic->next)
1440 if (ic->op == CALL || ic->op == PCALL)
1445 fprintf (stderr, "found parameter push with no function call\n");
1449 /* if the registers have been saved already or don't need to be then
1451 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1452 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1455 /* find the registers in use at this time
1456 and push them away to safety */
1457 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1461 if (options.useXstack)
1463 if (bitVectBitValue (rsave, R0_IDX))
1464 emitcode ("mov", "b,r0");
1465 emitcode ("mov", "r0,%s", spname);
1466 for (i = 0; i < mcs51_nRegs; i++)
1468 if (bitVectBitValue (rsave, i))
1471 emitcode ("mov", "a,b");
1473 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1474 emitcode ("movx", "@r0,a");
1475 emitcode ("inc", "r0");
1478 emitcode ("mov", "%s,r0", spname);
1479 if (bitVectBitValue (rsave, R0_IDX))
1480 emitcode ("mov", "r0,b");
1483 for (i = 0; i < mcs51_nRegs; i++)
1485 if (bitVectBitValue (rsave, i))
1486 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1489 detype = getSpec (operandType (IC_LEFT (ic)));
1492 /*-----------------------------------------------------------------*/
1493 /* unsaveRegisters - pop the pushed registers */
1494 /*-----------------------------------------------------------------*/
1496 unsaveRegisters (iCode * ic)
1500 /* find the registers in use at this time
1501 and push them away to safety */
1502 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1505 if (options.useXstack)
1507 emitcode ("mov", "r0,%s", spname);
1508 for (i = mcs51_nRegs; i >= 0; i--)
1510 if (bitVectBitValue (rsave, i))
1512 emitcode ("dec", "r0");
1513 emitcode ("movx", "a,@r0");
1515 emitcode ("mov", "b,a");
1517 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1521 emitcode ("mov", "%s,r0", spname);
1522 if (bitVectBitValue (rsave, R0_IDX))
1523 emitcode ("mov", "r0,b");
1526 for (i = mcs51_nRegs; i >= 0; i--)
1528 if (bitVectBitValue (rsave, i))
1529 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1535 /*-----------------------------------------------------------------*/
1537 /*-----------------------------------------------------------------*/
1539 pushSide (operand * oper, int size)
1544 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1545 if (AOP_TYPE (oper) != AOP_REG &&
1546 AOP_TYPE (oper) != AOP_DIR &&
1549 emitcode ("mov", "a,%s", l);
1550 emitcode ("push", "acc");
1553 emitcode ("push", "%s", l);
1557 /*-----------------------------------------------------------------*/
1558 /* assignResultValue - */
1559 /*-----------------------------------------------------------------*/
1561 assignResultValue (operand * oper)
1564 int size = AOP_SIZE (oper);
1567 aopPut (AOP (oper), fReturn[offset], offset);
1573 /*-----------------------------------------------------------------*/
1574 /* genXpush - pushes onto the external stack */
1575 /*-----------------------------------------------------------------*/
1577 genXpush (iCode * ic)
1579 asmop *aop = newAsmop (0);
1581 int size, offset = 0;
1583 aopOp (IC_LEFT (ic), ic, FALSE);
1584 r = getFreePtr (ic, &aop, FALSE);
1587 emitcode ("mov", "%s,_spx", r->name);
1589 size = AOP_SIZE (IC_LEFT (ic));
1593 char *l = aopGet (AOP (IC_LEFT (ic)),
1594 offset++, FALSE, FALSE);
1596 emitcode ("movx", "@%s,a", r->name);
1597 emitcode ("inc", "%s", r->name);
1602 emitcode ("mov", "_spx,%s", r->name);
1604 freeAsmop (NULL, aop, ic, TRUE);
1605 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1608 /*-----------------------------------------------------------------*/
1609 /* genIpush - genrate code for pushing this gets a little complex */
1610 /*-----------------------------------------------------------------*/
1612 genIpush (iCode * ic)
1614 int size, offset = 0;
1617 D(emitcode (";", "genIpush"));
1619 /* if this is not a parm push : ie. it is spill push
1620 and spill push is always done on the local stack */
1624 /* and the item is spilt then do nothing */
1625 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1628 aopOp (IC_LEFT (ic), ic, FALSE);
1629 size = AOP_SIZE (IC_LEFT (ic));
1630 /* push it on the stack */
1633 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1639 emitcode ("push", "%s", l);
1644 /* this is a paramter push: in this case we call
1645 the routine to find the call and save those
1646 registers that need to be saved */
1649 /* if use external stack then call the external
1650 stack pushing routine */
1651 if (options.useXstack)
1657 /* then do the push */
1658 aopOp (IC_LEFT (ic), ic, FALSE);
1661 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1662 size = AOP_SIZE (IC_LEFT (ic));
1666 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1667 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1668 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1671 emitcode ("mov", "a,%s", l);
1672 emitcode ("push", "acc");
1675 emitcode ("push", "%s", l);
1678 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1681 /*-----------------------------------------------------------------*/
1682 /* genIpop - recover the registers: can happen only for spilling */
1683 /*-----------------------------------------------------------------*/
1685 genIpop (iCode * ic)
1690 /* if the temp was not pushed then */
1691 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1694 aopOp (IC_LEFT (ic), ic, FALSE);
1695 size = AOP_SIZE (IC_LEFT (ic));
1696 offset = (size - 1);
1698 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1701 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1704 /*-----------------------------------------------------------------*/
1705 /* unsaveRBank - restores the resgister bank from stack */
1706 /*-----------------------------------------------------------------*/
1708 unsaveRBank (int bank, iCode * ic, bool popPsw)
1714 if (options.useXstack)
1718 /* Assume r0 is available for use. */
1719 r = mcs51_regWithIdx (R0_IDX);;
1724 r = getFreePtr (ic, &aop, FALSE);
1726 emitcode ("mov", "%s,_spx", r->name);
1731 if (options.useXstack)
1733 emitcode ("movx", "a,@%s", r->name);
1734 emitcode ("mov", "psw,a");
1735 emitcode ("dec", "%s", r->name);
1739 emitcode ("pop", "psw");
1743 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1745 if (options.useXstack)
1747 emitcode ("movx", "a,@%s", r->name);
1748 emitcode ("mov", "(%s+%d),a",
1749 regs8051[i].base, 8 * bank + regs8051[i].offset);
1750 emitcode ("dec", "%s", r->name);
1754 emitcode ("pop", "(%s+%d)",
1755 regs8051[i].base, 8 * bank + regs8051[i].offset);
1758 if (options.useXstack)
1760 emitcode ("mov", "_spx,%s", r->name);
1765 freeAsmop (NULL, aop, ic, TRUE);
1769 /*-----------------------------------------------------------------*/
1770 /* saveRBank - saves an entire register bank on the stack */
1771 /*-----------------------------------------------------------------*/
1773 saveRBank (int bank, iCode * ic, bool pushPsw)
1779 if (options.useXstack)
1783 /* Assume r0 is available for use. */
1784 r = mcs51_regWithIdx (R0_IDX);;
1789 r = getFreePtr (ic, &aop, FALSE);
1791 emitcode ("mov", "%s,_spx", r->name);
1794 for (i = 0; i < mcs51_nRegs; i++)
1796 if (options.useXstack)
1798 emitcode ("inc", "%s", r->name);
1799 emitcode ("mov", "a,(%s+%d)",
1800 regs8051[i].base, 8 * bank + regs8051[i].offset);
1801 emitcode ("movx", "@%s,a", r->name);
1804 emitcode ("push", "(%s+%d)",
1805 regs8051[i].base, 8 * bank + regs8051[i].offset);
1810 if (options.useXstack)
1812 emitcode ("mov", "a,psw");
1813 emitcode ("movx", "@%s,a", r->name);
1814 emitcode ("inc", "%s", r->name);
1815 emitcode ("mov", "_spx,%s", r->name);
1820 emitcode ("push", "psw");
1823 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1828 freeAsmop (NULL, aop, ic, TRUE);
1837 /*-----------------------------------------------------------------*/
1838 /* genCall - generates a call statement */
1839 /*-----------------------------------------------------------------*/
1841 genCall (iCode * ic)
1844 bool restoreBank = FALSE;
1845 bool swapBanks = FALSE;
1847 D(emitcode(";", "genCall"));
1848 /* if send set is not empty the assign */
1853 for (sic = setFirstItem (_G.sendSet); sic;
1854 sic = setNextItem (_G.sendSet))
1856 int size, offset = 0;
1857 aopOp (IC_LEFT (sic), sic, FALSE);
1858 size = AOP_SIZE (IC_LEFT (sic));
1861 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1863 if (strcmp (l, fReturn[offset]))
1864 emitcode ("mov", "%s,%s",
1869 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1874 /* if we are calling a not _naked function that is not using
1875 the same register bank then we need to save the
1876 destination registers on the stack */
1877 detype = getSpec (operandType (IC_LEFT (ic)));
1878 if (detype && !SPEC_NAKED(detype) &&
1879 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1880 IS_ISR (currFunc->etype))
1884 /* This is unexpected; the bank should have been saved in
1887 saveRBank (SPEC_BANK (detype), ic, FALSE);
1893 /* if caller saves & we have not saved then */
1899 emitcode ("mov", "psw,#0x%02x",
1900 ((SPEC_BANK(detype)) << 3) & 0xff);
1904 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1905 OP_SYMBOL (IC_LEFT (ic))->rname :
1906 OP_SYMBOL (IC_LEFT (ic))->name));
1910 emitcode ("mov", "psw,#0x%02x",
1911 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1914 /* if we need assign a result value */
1915 if ((IS_ITEMP (IC_RESULT (ic)) &&
1916 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1917 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1918 IS_TRUE_SYMOP (IC_RESULT (ic)))
1922 aopOp (IC_RESULT (ic), ic, FALSE);
1925 assignResultValue (IC_RESULT (ic));
1927 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1930 /* adjust the stack for parameters if
1935 if (ic->parmBytes > 3)
1937 emitcode ("mov", "a,%s", spname);
1938 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1939 emitcode ("mov", "%s,a", spname);
1942 for (i = 0; i < ic->parmBytes; i++)
1943 emitcode ("dec", "%s", spname);
1946 /* if we hade saved some registers then unsave them */
1947 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1948 unsaveRegisters (ic);
1950 /* if register bank was saved then pop them */
1952 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1955 /*-----------------------------------------------------------------*/
1956 /* genPcall - generates a call by pointer statement */
1957 /*-----------------------------------------------------------------*/
1959 genPcall (iCode * ic)
1962 symbol *rlbl = newiTempLabel (NULL);
1965 /* if caller saves & we have not saved then */
1969 /* if we are calling a function that is not using
1970 the same register bank then we need to save the
1971 destination registers on the stack */
1972 detype = getSpec (operandType (IC_LEFT (ic)));
1974 IS_ISR (currFunc->etype) &&
1975 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1976 saveRBank (SPEC_BANK (detype), ic, TRUE);
1979 /* push the return address on to the stack */
1980 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1981 emitcode ("push", "acc");
1982 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1983 emitcode ("push", "acc");
1985 /* now push the calling address */
1986 aopOp (IC_LEFT (ic), ic, FALSE);
1988 pushSide (IC_LEFT (ic), FPTRSIZE);
1990 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1992 /* if send set is not empty the assign */
1997 for (sic = setFirstItem (_G.sendSet); sic;
1998 sic = setNextItem (_G.sendSet))
2000 int size, offset = 0;
2001 aopOp (IC_LEFT (sic), sic, FALSE);
2002 size = AOP_SIZE (IC_LEFT (sic));
2005 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2007 if (strcmp (l, fReturn[offset]))
2008 emitcode ("mov", "%s,%s",
2013 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2018 emitcode ("ret", "");
2019 emitcode ("", "%05d$:", (rlbl->key + 100));
2022 /* if we need assign a result value */
2023 if ((IS_ITEMP (IC_RESULT (ic)) &&
2024 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2025 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2026 IS_TRUE_SYMOP (IC_RESULT (ic)))
2030 aopOp (IC_RESULT (ic), ic, FALSE);
2033 assignResultValue (IC_RESULT (ic));
2035 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2038 /* adjust the stack for parameters if
2043 if (ic->parmBytes > 3)
2045 emitcode ("mov", "a,%s", spname);
2046 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2047 emitcode ("mov", "%s,a", spname);
2050 for (i = 0; i < ic->parmBytes; i++)
2051 emitcode ("dec", "%s", spname);
2055 /* if register bank was saved then unsave them */
2057 (SPEC_BANK (currFunc->etype) !=
2058 SPEC_BANK (detype)))
2059 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2061 /* if we hade saved some registers then
2064 unsaveRegisters (ic);
2068 /*-----------------------------------------------------------------*/
2069 /* resultRemat - result is rematerializable */
2070 /*-----------------------------------------------------------------*/
2072 resultRemat (iCode * ic)
2074 if (SKIP_IC (ic) || ic->op == IFX)
2077 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2079 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2080 if (sym->remat && !POINTER_SET (ic))
2087 #if defined(__BORLANDC__) || defined(_MSC_VER)
2088 #define STRCASECMP stricmp
2090 #define STRCASECMP strcasecmp
2093 /*-----------------------------------------------------------------*/
2094 /* inExcludeList - return 1 if the string is in exclude Reg list */
2095 /*-----------------------------------------------------------------*/
2097 inExcludeList (char *s)
2101 if (options.excludeRegs[i] &&
2102 STRCASECMP (options.excludeRegs[i], "none") == 0)
2105 for (i = 0; options.excludeRegs[i]; i++)
2107 if (options.excludeRegs[i] &&
2108 STRCASECMP (s, options.excludeRegs[i]) == 0)
2114 /*-----------------------------------------------------------------*/
2115 /* genFunction - generated code for function entry */
2116 /*-----------------------------------------------------------------*/
2118 genFunction (iCode * ic)
2122 bool switchedPSW = FALSE;
2125 /* create the function header */
2126 emitcode (";", "-----------------------------------------");
2127 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2128 emitcode (";", "-----------------------------------------");
2130 emitcode ("", "%s:", sym->rname);
2131 fetype = getSpec (operandType (IC_LEFT (ic)));
2133 if (SPEC_NAKED(fetype))
2135 emitcode(";", "naked function: no prologue.");
2139 /* if critical function then turn interrupts off */
2140 if (SPEC_CRTCL (fetype))
2141 emitcode ("clr", "ea");
2143 /* here we need to generate the equates for the
2144 register bank if required */
2145 if (SPEC_BANK (fetype) != rbank)
2149 rbank = SPEC_BANK (fetype);
2150 for (i = 0; i < mcs51_nRegs; i++)
2152 if (strcmp (regs8051[i].base, "0") == 0)
2153 emitcode ("", "%s = 0x%02x",
2155 8 * rbank + regs8051[i].offset);
2157 emitcode ("", "%s = %s + 0x%02x",
2160 8 * rbank + regs8051[i].offset);
2164 /* if this is an interrupt service routine then
2165 save acc, b, dpl, dph */
2166 if (IS_ISR (sym->etype))
2169 if (!inExcludeList ("acc"))
2170 emitcode ("push", "acc");
2171 if (!inExcludeList ("b"))
2172 emitcode ("push", "b");
2173 if (!inExcludeList ("dpl"))
2174 emitcode ("push", "dpl");
2175 if (!inExcludeList ("dph"))
2176 emitcode ("push", "dph");
2177 /* if this isr has no bank i.e. is going to
2178 run with bank 0 , then we need to save more
2180 if (!SPEC_BANK (sym->etype))
2183 /* if this function does not call any other
2184 function then we can be economical and
2185 save only those registers that are used */
2190 /* if any registers used */
2193 /* save the registers used */
2194 for (i = 0; i < sym->regsUsed->size; i++)
2196 if (bitVectBitValue (sym->regsUsed, i) ||
2197 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2198 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2205 /* this function has a function call cannot
2206 determines register usage so we will have to push the
2208 saveRBank (0, ic, FALSE);
2213 /* This ISR uses a non-zero bank.
2215 * We assume that the bank is available for our
2218 * However, if this ISR calls a function which uses some
2219 * other bank, we must save that bank entirely.
2221 unsigned long banksToSave = 0;
2226 #define MAX_REGISTER_BANKS 4
2231 for (i = ic; i; i = i->next)
2233 if (i->op == ENDFUNCTION)
2235 /* we got to the end OK. */
2243 detype = getSpec(operandType (IC_LEFT(i)));
2245 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2247 /* Mark this bank for saving. */
2248 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2250 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2254 banksToSave |= (1 << SPEC_BANK(detype));
2257 /* And note that we don't need to do it in
2265 /* This is a mess; we have no idea what
2266 * register bank the called function might
2269 * The only thing I can think of to do is
2270 * throw a warning and hope.
2272 werror(W_FUNCPTR_IN_USING_ISR);
2276 if (banksToSave && options.useXstack)
2278 /* Since we aren't passing it an ic,
2279 * saveRBank will assume r0 is available to abuse.
2281 * So switch to our (trashable) bank now, so
2282 * the caller's R0 isn't trashed.
2284 emitcode ("push", "psw");
2285 emitcode ("mov", "psw,#0x%02x",
2286 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2290 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2292 if (banksToSave & (1 << ix))
2294 saveRBank(ix, NULL, FALSE);
2298 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2303 /* if callee-save to be used for this function
2304 then save the registers being used in this function */
2305 if (sym->calleeSave)
2309 /* if any registers used */
2312 /* save the registers used */
2313 for (i = 0; i < sym->regsUsed->size; i++)
2315 if (bitVectBitValue (sym->regsUsed, i) ||
2316 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2318 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2326 /* set the register bank to the desired value */
2327 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2330 emitcode ("push", "psw");
2331 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2334 if (IS_RENT (sym->etype) || options.stackAuto)
2337 if (options.useXstack)
2339 emitcode ("mov", "r0,%s", spname);
2340 emitcode ("mov", "a,_bp");
2341 emitcode ("movx", "@r0,a");
2342 emitcode ("inc", "%s", spname);
2346 /* set up the stack */
2347 emitcode ("push", "_bp"); /* save the callers stack */
2349 emitcode ("mov", "_bp,%s", spname);
2352 /* adjust the stack for the function */
2358 werror (W_STACK_OVERFLOW, sym->name);
2360 if (i > 3 && sym->recvSize < 4)
2363 emitcode ("mov", "a,sp");
2364 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2365 emitcode ("mov", "sp,a");
2370 emitcode ("inc", "sp");
2376 emitcode ("mov", "a,_spx");
2377 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2378 emitcode ("mov", "_spx,a");
2383 /*-----------------------------------------------------------------*/
2384 /* genEndFunction - generates epilogue for functions */
2385 /*-----------------------------------------------------------------*/
2387 genEndFunction (iCode * ic)
2389 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2391 if (SPEC_NAKED(sym->etype))
2393 emitcode(";", "naked function: no epilogue.");
2397 if (IS_RENT (sym->etype) || options.stackAuto)
2399 emitcode ("mov", "%s,_bp", spname);
2402 /* if use external stack but some variables were
2403 added to the local stack then decrement the
2405 if (options.useXstack && sym->stack)
2407 emitcode ("mov", "a,sp");
2408 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2409 emitcode ("mov", "sp,a");
2413 if ((IS_RENT (sym->etype) || options.stackAuto))
2415 if (options.useXstack)
2417 emitcode ("mov", "r0,%s", spname);
2418 emitcode ("movx", "a,@r0");
2419 emitcode ("mov", "_bp,a");
2420 emitcode ("dec", "%s", spname);
2424 emitcode ("pop", "_bp");
2428 /* restore the register bank */
2429 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2431 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2432 || !options.useXstack)
2434 /* Special case of ISR using non-zero bank with useXstack
2437 emitcode ("pop", "psw");
2441 if (IS_ISR (sym->etype))
2444 /* now we need to restore the registers */
2445 /* if this isr has no bank i.e. is going to
2446 run with bank 0 , then we need to save more
2448 if (!SPEC_BANK (sym->etype))
2450 /* if this function does not call any other
2451 function then we can be economical and
2452 save only those registers that are used */
2457 /* if any registers used */
2460 /* save the registers used */
2461 for (i = sym->regsUsed->size; i >= 0; i--)
2463 if (bitVectBitValue (sym->regsUsed, i) ||
2464 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2465 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2472 /* this function has a function call cannot
2473 determines register usage so we will have to pop the
2475 unsaveRBank (0, ic, FALSE);
2480 /* This ISR uses a non-zero bank.
2482 * Restore any register banks saved by genFunction
2485 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2488 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2490 if (savedBanks & (1 << ix))
2492 unsaveRBank(ix, NULL, FALSE);
2496 if (options.useXstack)
2498 /* Restore bank AFTER calling unsaveRBank,
2499 * since it can trash r0.
2501 emitcode ("pop", "psw");
2505 if (!inExcludeList ("dph"))
2506 emitcode ("pop", "dph");
2507 if (!inExcludeList ("dpl"))
2508 emitcode ("pop", "dpl");
2509 if (!inExcludeList ("b"))
2510 emitcode ("pop", "b");
2511 if (!inExcludeList ("acc"))
2512 emitcode ("pop", "acc");
2514 if (SPEC_CRTCL (sym->etype))
2515 emitcode ("setb", "ea");
2517 /* if debug then send end of function */
2518 /* if (options.debug && currFunc) */
2519 if (options.debug && currFunc)
2522 emitcode ("", "C$%s$%d$%d$%d ==.",
2523 FileBaseName (ic->filename), currFunc->lastLine,
2524 ic->level, ic->block);
2525 if (IS_STATIC (currFunc->etype))
2526 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2528 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2532 emitcode ("reti", "");
2536 if (SPEC_CRTCL (sym->etype))
2537 emitcode ("setb", "ea");
2539 if (sym->calleeSave)
2543 /* if any registers used */
2546 /* save the registers used */
2547 for (i = sym->regsUsed->size; i >= 0; i--)
2549 if (bitVectBitValue (sym->regsUsed, i) ||
2550 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2551 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2557 /* if debug then send end of function */
2558 if (options.debug && currFunc)
2561 emitcode ("", "C$%s$%d$%d$%d ==.",
2562 FileBaseName (ic->filename), currFunc->lastLine,
2563 ic->level, ic->block);
2564 if (IS_STATIC (currFunc->etype))
2565 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2567 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2571 emitcode ("ret", "");
2576 /*-----------------------------------------------------------------*/
2577 /* genRet - generate code for return statement */
2578 /*-----------------------------------------------------------------*/
2582 int size, offset = 0, pushed = 0;
2584 /* if we have no return value then
2585 just generate the "ret" */
2589 /* we have something to return then
2590 move the return value into place */
2591 aopOp (IC_LEFT (ic), ic, FALSE);
2592 size = AOP_SIZE (IC_LEFT (ic));
2597 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2600 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2602 emitcode ("push", "%s", l);
2607 l = aopGet (AOP (IC_LEFT (ic)), offset,
2609 if (strcmp (fReturn[offset], l))
2610 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2619 if (strcmp (fReturn[pushed], "a"))
2620 emitcode ("pop", fReturn[pushed]);
2622 emitcode ("pop", "acc");
2625 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2628 /* generate a jump to the return label
2629 if the next is not the return statement */
2630 if (!(ic->next && ic->next->op == LABEL &&
2631 IC_LABEL (ic->next) == returnLabel))
2633 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2637 /*-----------------------------------------------------------------*/
2638 /* genLabel - generates a label */
2639 /*-----------------------------------------------------------------*/
2641 genLabel (iCode * ic)
2643 /* special case never generate */
2644 if (IC_LABEL (ic) == entryLabel)
2647 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2650 /*-----------------------------------------------------------------*/
2651 /* genGoto - generates a ljmp */
2652 /*-----------------------------------------------------------------*/
2654 genGoto (iCode * ic)
2656 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2659 /*-----------------------------------------------------------------*/
2660 /* findLabelBackwards: walks back through the iCode chain looking */
2661 /* for the given label. Returns number of iCode instructions */
2662 /* between that label and given ic. */
2663 /* Returns zero if label not found. */
2664 /*-----------------------------------------------------------------*/
2666 findLabelBackwards (iCode * ic, int key)
2675 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2677 /* printf("findLabelBackwards = %d\n", count); */
2685 /*-----------------------------------------------------------------*/
2686 /* genPlusIncr :- does addition with increment if possible */
2687 /*-----------------------------------------------------------------*/
2689 genPlusIncr (iCode * ic)
2691 unsigned int icount;
2692 unsigned int size = getDataSize (IC_RESULT (ic));
2694 /* will try to generate an increment */
2695 /* if the right side is not a literal
2697 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2700 /* if the literal value of the right hand side
2701 is greater than 4 then it is not worth it */
2702 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2705 /* if increment 16 bits in register */
2706 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2714 /* If the next instruction is a goto and the goto target
2715 * is < 10 instructions previous to this, we can generate
2716 * jumps straight to that target.
2718 if (ic->next && ic->next->op == GOTO
2719 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2720 && labelRange <= 10)
2722 emitcode (";", "tail increment optimized");
2723 tlbl = IC_LABEL (ic->next);
2728 tlbl = newiTempLabel (NULL);
2731 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2732 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2733 IS_AOP_PREG (IC_RESULT (ic)))
2734 emitcode ("cjne", "%s,#0x00,%05d$"
2735 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2739 emitcode ("clr", "a");
2740 emitcode ("cjne", "a,%s,%05d$"
2741 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2745 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2748 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2749 IS_AOP_PREG (IC_RESULT (ic)))
2750 emitcode ("cjne", "%s,#0x00,%05d$"
2751 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2754 emitcode ("cjne", "a,%s,%05d$"
2755 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2758 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2762 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2763 IS_AOP_PREG (IC_RESULT (ic)))
2764 emitcode ("cjne", "%s,#0x00,%05d$"
2765 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2769 emitcode ("cjne", "a,%s,%05d$"
2770 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2773 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2778 emitcode ("", "%05d$:", tlbl->key + 100);
2783 /* if the sizes are greater than 1 then we cannot */
2784 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2785 AOP_SIZE (IC_LEFT (ic)) > 1)
2788 /* we can if the aops of the left & result match or
2789 if they are in registers and the registers are the
2791 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2796 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2797 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2798 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2804 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2813 /*-----------------------------------------------------------------*/
2814 /* outBitAcc - output a bit in acc */
2815 /*-----------------------------------------------------------------*/
2817 outBitAcc (operand * result)
2819 symbol *tlbl = newiTempLabel (NULL);
2820 /* if the result is a bit */
2821 if (AOP_TYPE (result) == AOP_CRY)
2823 aopPut (AOP (result), "a", 0);
2827 emitcode ("jz", "%05d$", tlbl->key + 100);
2828 emitcode ("mov", "a,%s", one);
2829 emitcode ("", "%05d$:", tlbl->key + 100);
2834 /*-----------------------------------------------------------------*/
2835 /* genPlusBits - generates code for addition of two bits */
2836 /*-----------------------------------------------------------------*/
2838 genPlusBits (iCode * ic)
2840 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2842 symbol *lbl = newiTempLabel (NULL);
2843 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2844 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2845 emitcode ("cpl", "c");
2846 emitcode ("", "%05d$:", (lbl->key + 100));
2847 outBitC (IC_RESULT (ic));
2851 emitcode ("clr", "a");
2852 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2853 emitcode ("rlc", "a");
2854 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2855 emitcode ("addc", "a,#0x00");
2856 outAcc (IC_RESULT (ic));
2861 /* This is the original version of this code.
2863 * This is being kept around for reference,
2864 * because I am not entirely sure I got it right...
2867 adjustArithmeticResult (iCode * ic)
2869 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2870 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2871 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2872 aopPut (AOP (IC_RESULT (ic)),
2873 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2876 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2877 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2878 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2879 aopPut (AOP (IC_RESULT (ic)),
2880 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2883 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2884 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2885 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2886 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2887 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2890 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2891 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2895 /* This is the pure and virtuous version of this code.
2896 * I'm pretty certain it's right, but not enough to toss the old
2900 adjustArithmeticResult (iCode * ic)
2902 if (opIsGptr (IC_RESULT (ic)) &&
2903 opIsGptr (IC_LEFT (ic)) &&
2904 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2906 aopPut (AOP (IC_RESULT (ic)),
2907 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2911 if (opIsGptr (IC_RESULT (ic)) &&
2912 opIsGptr (IC_RIGHT (ic)) &&
2913 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2915 aopPut (AOP (IC_RESULT (ic)),
2916 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2920 if (opIsGptr (IC_RESULT (ic)) &&
2921 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2922 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2923 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2924 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2927 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2928 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2933 /*-----------------------------------------------------------------*/
2934 /* genPlus - generates code for addition */
2935 /*-----------------------------------------------------------------*/
2937 genPlus (iCode * ic)
2939 int size, offset = 0;
2941 /* special cases :- */
2943 aopOp (IC_LEFT (ic), ic, FALSE);
2944 aopOp (IC_RIGHT (ic), ic, FALSE);
2945 aopOp (IC_RESULT (ic), ic, TRUE);
2947 /* if literal, literal on the right or
2948 if left requires ACC or right is already
2950 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2951 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2952 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2954 operand *t = IC_RIGHT (ic);
2955 IC_RIGHT (ic) = IC_LEFT (ic);
2959 /* if both left & right are in bit
2961 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2962 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2968 /* if left in bit space & right literal */
2969 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2970 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2972 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2973 /* if result in bit space */
2974 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2976 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2977 emitcode ("cpl", "c");
2978 outBitC (IC_RESULT (ic));
2982 size = getDataSize (IC_RESULT (ic));
2985 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2986 emitcode ("addc", "a,#00");
2987 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2993 /* if I can do an increment instead
2994 of add then GOOD for ME */
2995 if (genPlusIncr (ic) == TRUE)
2998 size = getDataSize (IC_RESULT (ic));
3002 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3004 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3006 emitcode ("add", "a,%s",
3007 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3009 emitcode ("addc", "a,%s",
3010 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3014 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3016 emitcode ("add", "a,%s",
3017 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3019 emitcode ("addc", "a,%s",
3020 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3022 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3025 adjustArithmeticResult (ic);
3028 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3029 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3030 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3033 /*-----------------------------------------------------------------*/
3034 /* genMinusDec :- does subtraction with deccrement if possible */
3035 /*-----------------------------------------------------------------*/
3037 genMinusDec (iCode * ic)
3039 unsigned int icount;
3040 unsigned int size = getDataSize (IC_RESULT (ic));
3042 /* will try to generate an increment */
3043 /* if the right side is not a literal
3045 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3048 /* if the literal value of the right hand side
3049 is greater than 4 then it is not worth it */
3050 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3053 /* if decrement 16 bits in register */
3054 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3062 /* If the next instruction is a goto and the goto target
3063 * is <= 10 instructions previous to this, we can generate
3064 * jumps straight to that target.
3066 if (ic->next && ic->next->op == GOTO
3067 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3068 && labelRange <= 10)
3070 emitcode (";", "tail decrement optimized");
3071 tlbl = IC_LABEL (ic->next);
3076 tlbl = newiTempLabel (NULL);
3080 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3081 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3082 IS_AOP_PREG (IC_RESULT (ic)))
3083 emitcode ("cjne", "%s,#0xff,%05d$"
3084 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3088 emitcode ("mov", "a,#0xff");
3089 emitcode ("cjne", "a,%s,%05d$"
3090 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3093 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3096 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3097 IS_AOP_PREG (IC_RESULT (ic)))
3098 emitcode ("cjne", "%s,#0xff,%05d$"
3099 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3103 emitcode ("cjne", "a,%s,%05d$"
3104 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3107 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3111 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3112 IS_AOP_PREG (IC_RESULT (ic)))
3113 emitcode ("cjne", "%s,#0xff,%05d$"
3114 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3118 emitcode ("cjne", "a,%s,%05d$"
3119 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3122 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3126 emitcode ("", "%05d$:", tlbl->key + 100);
3131 /* if the sizes are greater than 1 then we cannot */
3132 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3133 AOP_SIZE (IC_LEFT (ic)) > 1)
3136 /* we can if the aops of the left & result match or
3137 if they are in registers and the registers are the
3139 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3143 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3151 /*-----------------------------------------------------------------*/
3152 /* addSign - complete with sign */
3153 /*-----------------------------------------------------------------*/
3155 addSign (operand * result, int offset, int sign)
3157 int size = (getDataSize (result) - offset);
3162 emitcode ("rlc", "a");
3163 emitcode ("subb", "a,acc");
3165 aopPut (AOP (result), "a", offset++);
3169 aopPut (AOP (result), zero, offset++);
3173 /*-----------------------------------------------------------------*/
3174 /* genMinusBits - generates code for subtraction of two bits */
3175 /*-----------------------------------------------------------------*/
3177 genMinusBits (iCode * ic)
3179 symbol *lbl = newiTempLabel (NULL);
3180 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3182 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3183 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3184 emitcode ("cpl", "c");
3185 emitcode ("", "%05d$:", (lbl->key + 100));
3186 outBitC (IC_RESULT (ic));
3190 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3191 emitcode ("subb", "a,acc");
3192 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3193 emitcode ("inc", "a");
3194 emitcode ("", "%05d$:", (lbl->key + 100));
3195 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3196 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3200 /*-----------------------------------------------------------------*/
3201 /* genMinus - generates code for subtraction */
3202 /*-----------------------------------------------------------------*/
3204 genMinus (iCode * ic)
3206 int size, offset = 0;
3207 unsigned long lit = 0L;
3209 aopOp (IC_LEFT (ic), ic, FALSE);
3210 aopOp (IC_RIGHT (ic), ic, FALSE);
3211 aopOp (IC_RESULT (ic), ic, TRUE);
3213 /* special cases :- */
3214 /* if both left & right are in bit space */
3215 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3216 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3222 /* if I can do an decrement instead
3223 of subtract then GOOD for ME */
3224 if (genMinusDec (ic) == TRUE)
3227 size = getDataSize (IC_RESULT (ic));
3229 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3235 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3239 /* if literal, add a,#-lit, else normal subb */
3242 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3243 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3244 emitcode ("subb", "a,%s",
3245 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3248 /* first add without previous c */
3250 emitcode ("add", "a,#0x%02x",
3251 (unsigned int) (lit & 0x0FFL));
3253 emitcode ("addc", "a,#0x%02x",
3254 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3256 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3259 adjustArithmeticResult (ic);
3262 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3263 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3264 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3268 /*-----------------------------------------------------------------*/
3269 /* genMultbits :- multiplication of bits */
3270 /*-----------------------------------------------------------------*/
3272 genMultbits (operand * left,
3276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3277 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3282 /*-----------------------------------------------------------------*/
3283 /* genMultOneByte : 8*8=8/16 bit multiplication */
3284 /*-----------------------------------------------------------------*/
3286 genMultOneByte (operand * left,
3290 sym_link *opetype = operandType (result);
3292 int size=AOP_SIZE(result);
3294 if (size<1 || size>2) {
3295 // this should never happen
3296 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3297 AOP_SIZE(result), __FILE__, lineno);
3301 /* (if two literals: the value is computed before) */
3302 /* if one literal, literal on the right */
3303 if (AOP_TYPE (left) == AOP_LIT)
3308 //emitcode (";", "swapped left and right");
3311 if (SPEC_USIGN(opetype)
3312 // ignore the sign of left and right, what else can we do?
3313 || (SPEC_USIGN(operandType(left)) &&
3314 SPEC_USIGN(operandType(right)))) {
3315 // just an unsigned 8*8=8/16 multiply
3316 //emitcode (";","unsigned");
3317 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3318 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3319 emitcode ("mul", "ab");
3320 aopPut (AOP (result), "a", 0);
3322 aopPut (AOP (result), "b", 1);
3327 // we have to do a signed multiply
3329 //emitcode (";", "signed");
3330 emitcode ("clr", "F0"); // reset sign flag
3331 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3333 lbl=newiTempLabel(NULL);
3334 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3335 // left side is negative, 8-bit two's complement, this fails for -128
3336 emitcode ("setb", "F0"); // set sign flag
3337 emitcode ("cpl", "a");
3338 emitcode ("inc", "a");
3340 emitcode ("", "%05d$:", lbl->key+100);
3343 if (AOP_TYPE(right)==AOP_LIT) {
3344 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3345 /* AND literal negative */
3347 emitcode ("cpl", "F0"); // complement sign flag
3348 emitcode ("mov", "b,#0x%02x", -val);
3350 emitcode ("mov", "b,#0x%02x", val);
3353 lbl=newiTempLabel(NULL);
3354 emitcode ("mov", "b,a");
3355 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3356 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3357 // right side is negative, 8-bit two's complement
3358 emitcode ("cpl", "F0"); // complement sign flag
3359 emitcode ("cpl", "a");
3360 emitcode ("inc", "a");
3361 emitcode ("", "%05d$:", lbl->key+100);
3363 emitcode ("mul", "ab");
3365 lbl=newiTempLabel(NULL);
3366 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3367 // only ONE op was negative, we have to do a 8/16-bit two's complement
3368 emitcode ("cpl", "a"); // lsb
3370 emitcode ("inc", "a");
3372 emitcode ("add", "a,#1");
3373 emitcode ("xch", "a,b");
3374 emitcode ("cpl", "a"); // msb
3375 emitcode ("addc", "a,#0");
3376 emitcode ("xch", "a,b");
3379 emitcode ("", "%05d$:", lbl->key+100);
3380 aopPut (AOP (result), "a", 0);
3382 aopPut (AOP (result), "b", 1);
3386 /*-----------------------------------------------------------------*/
3387 /* genMult - generates code for multiplication */
3388 /*-----------------------------------------------------------------*/
3390 genMult (iCode * ic)
3392 operand *left = IC_LEFT (ic);
3393 operand *right = IC_RIGHT (ic);
3394 operand *result = IC_RESULT (ic);
3396 /* assign the amsops */
3397 aopOp (left, ic, FALSE);
3398 aopOp (right, ic, FALSE);
3399 aopOp (result, ic, TRUE);
3401 /* special cases first */
3403 if (AOP_TYPE (left) == AOP_CRY &&
3404 AOP_TYPE (right) == AOP_CRY)
3406 genMultbits (left, right, result);
3410 /* if both are of size == 1 */
3411 if (AOP_SIZE (left) == 1 &&
3412 AOP_SIZE (right) == 1)
3414 genMultOneByte (left, right, result);
3418 /* should have been converted to function call */
3422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3424 freeAsmop (result, NULL, ic, TRUE);
3427 /*-----------------------------------------------------------------*/
3428 /* genDivbits :- division of bits */
3429 /*-----------------------------------------------------------------*/
3431 genDivbits (operand * left,
3438 /* the result must be bit */
3439 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3440 l = aopGet (AOP (left), 0, FALSE, FALSE);
3444 emitcode ("div", "ab");
3445 emitcode ("rrc", "a");
3446 aopPut (AOP (result), "c", 0);
3449 /*-----------------------------------------------------------------*/
3450 /* genDivOneByte : 8 bit division */
3451 /*-----------------------------------------------------------------*/
3453 genDivOneByte (operand * left,
3457 sym_link *opetype = operandType (result);
3462 size = AOP_SIZE (result) - 1;
3464 /* signed or unsigned */
3465 if (SPEC_USIGN (opetype))
3467 /* unsigned is easy */
3468 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3469 l = aopGet (AOP (left), 0, FALSE, FALSE);
3471 emitcode ("div", "ab");
3472 aopPut (AOP (result), "a", 0);
3474 aopPut (AOP (result), zero, offset++);
3478 /* signed is a little bit more difficult */
3480 /* save the signs of the operands */
3481 l = aopGet (AOP (left), 0, FALSE, FALSE);
3483 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3484 emitcode ("push", "acc"); /* save it on the stack */
3486 /* now sign adjust for both left & right */
3487 l = aopGet (AOP (right), 0, FALSE, FALSE);
3489 lbl = newiTempLabel (NULL);
3490 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3491 emitcode ("cpl", "a");
3492 emitcode ("inc", "a");
3493 emitcode ("", "%05d$:", (lbl->key + 100));
3494 emitcode ("mov", "b,a");
3496 /* sign adjust left side */
3497 l = aopGet (AOP (left), 0, FALSE, FALSE);
3500 lbl = newiTempLabel (NULL);
3501 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3502 emitcode ("cpl", "a");
3503 emitcode ("inc", "a");
3504 emitcode ("", "%05d$:", (lbl->key + 100));
3506 /* now the division */
3507 emitcode ("div", "ab");
3508 /* we are interested in the lower order
3510 emitcode ("mov", "b,a");
3511 lbl = newiTempLabel (NULL);
3512 emitcode ("pop", "acc");
3513 /* if there was an over flow we don't
3514 adjust the sign of the result */
3515 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3516 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3518 emitcode ("clr", "a");
3519 emitcode ("subb", "a,b");
3520 emitcode ("mov", "b,a");
3521 emitcode ("", "%05d$:", (lbl->key + 100));
3523 /* now we are done */
3524 aopPut (AOP (result), "b", 0);
3527 emitcode ("mov", "c,b.7");
3528 emitcode ("subb", "a,acc");
3531 aopPut (AOP (result), "a", offset++);
3535 /*-----------------------------------------------------------------*/
3536 /* genDiv - generates code for division */
3537 /*-----------------------------------------------------------------*/
3541 operand *left = IC_LEFT (ic);
3542 operand *right = IC_RIGHT (ic);
3543 operand *result = IC_RESULT (ic);
3545 /* assign the amsops */
3546 aopOp (left, ic, FALSE);
3547 aopOp (right, ic, FALSE);
3548 aopOp (result, ic, TRUE);
3550 /* special cases first */
3552 if (AOP_TYPE (left) == AOP_CRY &&
3553 AOP_TYPE (right) == AOP_CRY)
3555 genDivbits (left, right, result);
3559 /* if both are of size == 1 */
3560 if (AOP_SIZE (left) == 1 &&
3561 AOP_SIZE (right) == 1)
3563 genDivOneByte (left, right, result);
3567 /* should have been converted to function call */
3570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3572 freeAsmop (result, NULL, ic, TRUE);
3575 /*-----------------------------------------------------------------*/
3576 /* genModbits :- modulus of bits */
3577 /*-----------------------------------------------------------------*/
3579 genModbits (operand * left,
3586 /* the result must be bit */
3587 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3588 l = aopGet (AOP (left), 0, FALSE, FALSE);
3592 emitcode ("div", "ab");
3593 emitcode ("mov", "a,b");
3594 emitcode ("rrc", "a");
3595 aopPut (AOP (result), "c", 0);
3598 /*-----------------------------------------------------------------*/
3599 /* genModOneByte : 8 bit modulus */
3600 /*-----------------------------------------------------------------*/
3602 genModOneByte (operand * left,
3606 sym_link *opetype = operandType (result);
3610 /* signed or unsigned */
3611 if (SPEC_USIGN (opetype))
3613 /* unsigned is easy */
3614 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3615 l = aopGet (AOP (left), 0, FALSE, FALSE);
3617 emitcode ("div", "ab");
3618 aopPut (AOP (result), "b", 0);
3622 /* signed is a little bit more difficult */
3624 /* save the signs of the operands */
3625 l = aopGet (AOP (left), 0, FALSE, FALSE);
3628 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3629 emitcode ("push", "acc"); /* save it on the stack */
3631 /* now sign adjust for both left & right */
3632 l = aopGet (AOP (right), 0, FALSE, FALSE);
3635 lbl = newiTempLabel (NULL);
3636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3637 emitcode ("cpl", "a");
3638 emitcode ("inc", "a");
3639 emitcode ("", "%05d$:", (lbl->key + 100));
3640 emitcode ("mov", "b,a");
3642 /* sign adjust left side */
3643 l = aopGet (AOP (left), 0, FALSE, FALSE);
3646 lbl = newiTempLabel (NULL);
3647 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3648 emitcode ("cpl", "a");
3649 emitcode ("inc", "a");
3650 emitcode ("", "%05d$:", (lbl->key + 100));
3652 /* now the multiplication */
3653 emitcode ("div", "ab");
3654 /* we are interested in the lower order
3656 lbl = newiTempLabel (NULL);
3657 emitcode ("pop", "acc");
3658 /* if there was an over flow we don't
3659 adjust the sign of the result */
3660 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3661 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3663 emitcode ("clr", "a");
3664 emitcode ("subb", "a,b");
3665 emitcode ("mov", "b,a");
3666 emitcode ("", "%05d$:", (lbl->key + 100));
3668 /* now we are done */
3669 aopPut (AOP (result), "b", 0);
3673 /*-----------------------------------------------------------------*/
3674 /* genMod - generates code for division */
3675 /*-----------------------------------------------------------------*/
3679 operand *left = IC_LEFT (ic);
3680 operand *right = IC_RIGHT (ic);
3681 operand *result = IC_RESULT (ic);
3683 /* assign the amsops */
3684 aopOp (left, ic, FALSE);
3685 aopOp (right, ic, FALSE);
3686 aopOp (result, ic, TRUE);
3688 /* special cases first */
3690 if (AOP_TYPE (left) == AOP_CRY &&
3691 AOP_TYPE (right) == AOP_CRY)
3693 genModbits (left, right, result);
3697 /* if both are of size == 1 */
3698 if (AOP_SIZE (left) == 1 &&
3699 AOP_SIZE (right) == 1)
3701 genModOneByte (left, right, result);
3705 /* should have been converted to function call */
3709 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3710 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3711 freeAsmop (result, NULL, ic, TRUE);
3714 /*-----------------------------------------------------------------*/
3715 /* genIfxJump :- will create a jump depending on the ifx */
3716 /*-----------------------------------------------------------------*/
3718 genIfxJump (iCode * ic, char *jval)
3721 symbol *tlbl = newiTempLabel (NULL);
3724 /* if true label then we jump if condition
3728 jlbl = IC_TRUE (ic);
3729 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3730 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3734 /* false label is present */
3735 jlbl = IC_FALSE (ic);
3736 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3737 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3739 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3740 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3742 emitcode (inst, "%05d$", tlbl->key + 100);
3743 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3744 emitcode ("", "%05d$:", tlbl->key + 100);
3746 /* mark the icode as generated */
3750 /*-----------------------------------------------------------------*/
3751 /* genCmp :- greater or less than comparison */
3752 /*-----------------------------------------------------------------*/
3754 genCmp (operand * left, operand * right,
3755 operand * result, iCode * ifx, int sign, iCode *ic)
3757 int size, offset = 0;
3758 unsigned long lit = 0L;
3760 /* if left & right are bit variables */
3761 if (AOP_TYPE (left) == AOP_CRY &&
3762 AOP_TYPE (right) == AOP_CRY)
3764 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3765 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3769 /* subtract right from left if at the
3770 end the carry flag is set then we know that
3771 left is greater than right */
3772 size = max (AOP_SIZE (left), AOP_SIZE (right));
3774 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3775 if ((size == 1) && !sign &&
3776 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3778 symbol *lbl = newiTempLabel (NULL);
3779 emitcode ("cjne", "%s,%s,%05d$",
3780 aopGet (AOP (left), offset, FALSE, FALSE),
3781 aopGet (AOP (right), offset, FALSE, FALSE),
3783 emitcode ("", "%05d$:", lbl->key + 100);
3787 if (AOP_TYPE (right) == AOP_LIT)
3789 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3790 /* optimize if(x < 0) or if(x >= 0) */
3799 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3800 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3802 genIfxJump (ifx, "acc.7");
3806 emitcode ("rlc", "a");
3814 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3815 if (sign && size == 0)
3817 emitcode ("xrl", "a,#0x80");
3818 if (AOP_TYPE (right) == AOP_LIT)
3820 unsigned long lit = (unsigned long)
3821 floatFromVal (AOP (right)->aopu.aop_lit);
3822 emitcode ("subb", "a,#0x%02x",
3823 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3827 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3828 emitcode ("xrl", "b,#0x80");
3829 emitcode ("subb", "a,b");
3833 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3839 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3840 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3841 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3847 /* if the result is used in the next
3848 ifx conditional branch then generate
3849 code a little differently */
3851 genIfxJump (ifx, "c");
3854 /* leave the result in acc */
3858 /*-----------------------------------------------------------------*/
3859 /* genCmpGt :- greater than comparison */
3860 /*-----------------------------------------------------------------*/
3862 genCmpGt (iCode * ic, iCode * ifx)
3864 operand *left, *right, *result;
3865 sym_link *letype, *retype;
3868 left = IC_LEFT (ic);
3869 right = IC_RIGHT (ic);
3870 result = IC_RESULT (ic);
3872 letype = getSpec (operandType (left));
3873 retype = getSpec (operandType (right));
3874 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3875 /* assign the amsops */
3876 aopOp (left, ic, FALSE);
3877 aopOp (right, ic, FALSE);
3878 aopOp (result, ic, TRUE);
3880 genCmp (right, left, result, ifx, sign,ic);
3882 freeAsmop (result, NULL, ic, TRUE);
3885 /*-----------------------------------------------------------------*/
3886 /* genCmpLt - less than comparisons */
3887 /*-----------------------------------------------------------------*/
3889 genCmpLt (iCode * ic, iCode * ifx)
3891 operand *left, *right, *result;
3892 sym_link *letype, *retype;
3895 left = IC_LEFT (ic);
3896 right = IC_RIGHT (ic);
3897 result = IC_RESULT (ic);
3899 letype = getSpec (operandType (left));
3900 retype = getSpec (operandType (right));
3901 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3903 /* assign the amsops */
3904 aopOp (left, ic, FALSE);
3905 aopOp (right, ic, FALSE);
3906 aopOp (result, ic, TRUE);
3908 genCmp (left, right, result, ifx, sign,ic);
3910 freeAsmop (result, NULL, ic, TRUE);
3913 /*-----------------------------------------------------------------*/
3914 /* gencjneshort - compare and jump if not equal */
3915 /*-----------------------------------------------------------------*/
3917 gencjneshort (operand * left, operand * right, symbol * lbl)
3919 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3921 unsigned long lit = 0L;
3923 /* if the left side is a literal or
3924 if the right is in a pointer register and left
3926 if ((AOP_TYPE (left) == AOP_LIT) ||
3927 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3933 if (AOP_TYPE (right) == AOP_LIT)
3934 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3936 /* if the right side is a literal then anything goes */
3937 if (AOP_TYPE (right) == AOP_LIT &&
3938 AOP_TYPE (left) != AOP_DIR)
3942 emitcode ("cjne", "%s,%s,%05d$",
3943 aopGet (AOP (left), offset, FALSE, FALSE),
3944 aopGet (AOP (right), offset, FALSE, FALSE),
3950 /* if the right side is in a register or in direct space or
3951 if the left is a pointer register & right is not */
3952 else if (AOP_TYPE (right) == AOP_REG ||
3953 AOP_TYPE (right) == AOP_DIR ||
3954 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3955 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3959 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3960 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3961 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3962 emitcode ("jnz", "%05d$", lbl->key + 100);
3964 emitcode ("cjne", "a,%s,%05d$",
3965 aopGet (AOP (right), offset, FALSE, TRUE),
3972 /* right is a pointer reg need both a & b */
3975 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3976 if (strcmp (l, "b"))
3977 emitcode ("mov", "b,%s", l);
3978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3979 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3985 /*-----------------------------------------------------------------*/
3986 /* gencjne - compare and jump if not equal */
3987 /*-----------------------------------------------------------------*/
3989 gencjne (operand * left, operand * right, symbol * lbl)
3991 symbol *tlbl = newiTempLabel (NULL);
3993 gencjneshort (left, right, lbl);
3995 emitcode ("mov", "a,%s", one);
3996 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3997 emitcode ("", "%05d$:", lbl->key + 100);
3998 emitcode ("clr", "a");
3999 emitcode ("", "%05d$:", tlbl->key + 100);
4002 /*-----------------------------------------------------------------*/
4003 /* genCmpEq - generates code for equal to */
4004 /*-----------------------------------------------------------------*/
4006 genCmpEq (iCode * ic, iCode * ifx)
4008 operand *left, *right, *result;
4010 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4011 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4012 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4014 /* if literal, literal on the right or
4015 if the right is in a pointer register and left
4017 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4018 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4020 operand *t = IC_RIGHT (ic);
4021 IC_RIGHT (ic) = IC_LEFT (ic);
4025 if (ifx && !AOP_SIZE (result))
4028 /* if they are both bit variables */
4029 if (AOP_TYPE (left) == AOP_CRY &&
4030 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4032 if (AOP_TYPE (right) == AOP_LIT)
4034 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4037 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4038 emitcode ("cpl", "c");
4042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4046 emitcode ("clr", "c");
4048 /* AOP_TYPE(right) == AOP_CRY */
4052 symbol *lbl = newiTempLabel (NULL);
4053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4054 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4055 emitcode ("cpl", "c");
4056 emitcode ("", "%05d$:", (lbl->key + 100));
4058 /* if true label then we jump if condition
4060 tlbl = newiTempLabel (NULL);
4063 emitcode ("jnc", "%05d$", tlbl->key + 100);
4064 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4068 emitcode ("jc", "%05d$", tlbl->key + 100);
4069 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4071 emitcode ("", "%05d$:", tlbl->key + 100);
4075 tlbl = newiTempLabel (NULL);
4076 gencjneshort (left, right, tlbl);
4079 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4080 emitcode ("", "%05d$:", tlbl->key + 100);
4084 symbol *lbl = newiTempLabel (NULL);
4085 emitcode ("sjmp", "%05d$", lbl->key + 100);
4086 emitcode ("", "%05d$:", tlbl->key + 100);
4087 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4088 emitcode ("", "%05d$:", lbl->key + 100);
4091 /* mark the icode as generated */
4096 /* if they are both bit variables */
4097 if (AOP_TYPE (left) == AOP_CRY &&
4098 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4100 if (AOP_TYPE (right) == AOP_LIT)
4102 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4105 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4106 emitcode ("cpl", "c");
4110 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4114 emitcode ("clr", "c");
4116 /* AOP_TYPE(right) == AOP_CRY */
4120 symbol *lbl = newiTempLabel (NULL);
4121 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4122 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4123 emitcode ("cpl", "c");
4124 emitcode ("", "%05d$:", (lbl->key + 100));
4127 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4134 genIfxJump (ifx, "c");
4137 /* if the result is used in an arithmetic operation
4138 then put the result in place */
4143 gencjne (left, right, newiTempLabel (NULL));
4144 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4146 aopPut (AOP (result), "a", 0);
4151 genIfxJump (ifx, "a");
4154 /* if the result is used in an arithmetic operation
4155 then put the result in place */
4156 if (AOP_TYPE (result) != AOP_CRY)
4158 /* leave the result in acc */
4162 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4163 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4164 freeAsmop (result, NULL, ic, TRUE);
4167 /*-----------------------------------------------------------------*/
4168 /* ifxForOp - returns the icode containing the ifx for operand */
4169 /*-----------------------------------------------------------------*/
4171 ifxForOp (operand * op, iCode * ic)
4173 /* if true symbol then needs to be assigned */
4174 if (IS_TRUE_SYMOP (op))
4177 /* if this has register type condition and
4178 the next instruction is ifx with the same operand
4179 and live to of the operand is upto the ifx only then */
4181 ic->next->op == IFX &&
4182 IC_COND (ic->next)->key == op->key &&
4183 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4189 /*-----------------------------------------------------------------*/
4190 /* hasInc - operand is incremented before any other use */
4191 /*-----------------------------------------------------------------*/
4193 hasInc (operand *op, iCode *ic)
4195 sym_link *type = operandType(op);
4196 sym_link *retype = getSpec (type);
4197 iCode *lic = ic->next;
4200 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4201 isize = getSize(type->next);
4203 /* if operand of the form op = op + <sizeof *op> */
4204 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4205 isOperandEqual(IC_RESULT(lic),op) &&
4206 isOperandLiteral(IC_RIGHT(lic)) &&
4207 operandLitValue(IC_RIGHT(lic)) == isize) {
4210 /* if the operand used or deffed */
4211 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4219 /*-----------------------------------------------------------------*/
4220 /* genAndOp - for && operation */
4221 /*-----------------------------------------------------------------*/
4223 genAndOp (iCode * ic)
4225 operand *left, *right, *result;
4228 /* note here that && operations that are in an
4229 if statement are taken away by backPatchLabels
4230 only those used in arthmetic operations remain */
4231 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4232 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4233 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4235 /* if both are bit variables */
4236 if (AOP_TYPE (left) == AOP_CRY &&
4237 AOP_TYPE (right) == AOP_CRY)
4239 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4240 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4245 tlbl = newiTempLabel (NULL);
4247 emitcode ("jz", "%05d$", tlbl->key + 100);
4249 emitcode ("", "%05d$:", tlbl->key + 100);
4253 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4254 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4255 freeAsmop (result, NULL, ic, TRUE);
4259 /*-----------------------------------------------------------------*/
4260 /* genOrOp - for || operation */
4261 /*-----------------------------------------------------------------*/
4263 genOrOp (iCode * ic)
4265 operand *left, *right, *result;
4268 /* note here that || operations that are in an
4269 if statement are taken away by backPatchLabels
4270 only those used in arthmetic operations remain */
4271 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4272 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4273 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4275 /* if both are bit variables */
4276 if (AOP_TYPE (left) == AOP_CRY &&
4277 AOP_TYPE (right) == AOP_CRY)
4279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4280 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4285 tlbl = newiTempLabel (NULL);
4287 emitcode ("jnz", "%05d$", tlbl->key + 100);
4289 emitcode ("", "%05d$:", tlbl->key + 100);
4293 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4294 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4295 freeAsmop (result, NULL, ic, TRUE);
4298 /*-----------------------------------------------------------------*/
4299 /* isLiteralBit - test if lit == 2^n */
4300 /*-----------------------------------------------------------------*/
4302 isLiteralBit (unsigned long lit)
4304 unsigned long pw[32] =
4305 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4306 0x100L, 0x200L, 0x400L, 0x800L,
4307 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4308 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4309 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4310 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4311 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4314 for (idx = 0; idx < 32; idx++)
4320 /*-----------------------------------------------------------------*/
4321 /* continueIfTrue - */
4322 /*-----------------------------------------------------------------*/
4324 continueIfTrue (iCode * ic)
4327 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4331 /*-----------------------------------------------------------------*/
4333 /*-----------------------------------------------------------------*/
4335 jumpIfTrue (iCode * ic)
4338 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4342 /*-----------------------------------------------------------------*/
4343 /* jmpTrueOrFalse - */
4344 /*-----------------------------------------------------------------*/
4346 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4348 // ugly but optimized by peephole
4351 symbol *nlbl = newiTempLabel (NULL);
4352 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4353 emitcode ("", "%05d$:", tlbl->key + 100);
4354 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4355 emitcode ("", "%05d$:", nlbl->key + 100);
4359 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4360 emitcode ("", "%05d$:", tlbl->key + 100);
4365 /*-----------------------------------------------------------------*/
4366 /* genAnd - code for and */
4367 /*-----------------------------------------------------------------*/
4369 genAnd (iCode * ic, iCode * ifx)
4371 operand *left, *right, *result;
4372 int size, offset = 0;
4373 unsigned long lit = 0L;
4377 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4378 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4379 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4382 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4384 AOP_TYPE (left), AOP_TYPE (right));
4385 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4387 AOP_SIZE (left), AOP_SIZE (right));
4390 /* if left is a literal & right is not then exchange them */
4391 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4392 AOP_NEEDSACC (left))
4394 operand *tmp = right;
4399 /* if result = right then exchange them */
4400 if (sameRegs (AOP (result), AOP (right)))
4402 operand *tmp = right;
4407 /* if right is bit then exchange them */
4408 if (AOP_TYPE (right) == AOP_CRY &&
4409 AOP_TYPE (left) != AOP_CRY)
4411 operand *tmp = right;
4415 if (AOP_TYPE (right) == AOP_LIT)
4416 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4418 size = AOP_SIZE (result);
4421 // result = bit & yy;
4422 if (AOP_TYPE (left) == AOP_CRY)
4424 // c = bit & literal;
4425 if (AOP_TYPE (right) == AOP_LIT)
4429 if (size && sameRegs (AOP (result), AOP (left)))
4432 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4437 if (size && (AOP_TYPE (result) == AOP_CRY))
4439 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4442 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4447 emitcode ("clr", "c");
4452 if (AOP_TYPE (right) == AOP_CRY)
4455 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4456 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4461 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4463 emitcode ("rrc", "a");
4464 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4472 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4473 genIfxJump (ifx, "c");
4477 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4478 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4479 if ((AOP_TYPE (right) == AOP_LIT) &&
4480 (AOP_TYPE (result) == AOP_CRY) &&
4481 (AOP_TYPE (left) != AOP_CRY))
4483 int posbit = isLiteralBit (lit);
4488 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4491 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4497 sprintf (buffer, "acc.%d", posbit & 0x07);
4498 genIfxJump (ifx, buffer);
4505 symbol *tlbl = newiTempLabel (NULL);
4506 int sizel = AOP_SIZE (left);
4508 emitcode ("setb", "c");
4511 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4513 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4515 if ((posbit = isLiteralBit (bytelit)) != 0)
4516 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4519 if (bytelit != 0x0FFL)
4520 emitcode ("anl", "a,%s",
4521 aopGet (AOP (right), offset, FALSE, TRUE));
4522 emitcode ("jnz", "%05d$", tlbl->key + 100);
4527 // bit = left & literal
4530 emitcode ("clr", "c");
4531 emitcode ("", "%05d$:", tlbl->key + 100);
4533 // if(left & literal)
4537 jmpTrueOrFalse (ifx, tlbl);
4545 /* if left is same as result */
4546 if (sameRegs (AOP (result), AOP (left)))
4548 for (; size--; offset++)
4550 if (AOP_TYPE (right) == AOP_LIT)
4552 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4554 else if (bytelit == 0)
4555 aopPut (AOP (result), zero, offset);
4556 else if (IS_AOP_PREG (result))
4558 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4559 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4560 aopPut (AOP (result), "a", offset);
4563 emitcode ("anl", "%s,%s",
4564 aopGet (AOP (left), offset, FALSE, TRUE),
4565 aopGet (AOP (right), offset, FALSE, FALSE));
4569 if (AOP_TYPE (left) == AOP_ACC)
4570 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4573 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4574 if (IS_AOP_PREG (result))
4576 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4577 aopPut (AOP (result), "a", offset);
4581 emitcode ("anl", "%s,a",
4582 aopGet (AOP (left), offset, FALSE, TRUE));
4589 // left & result in different registers
4590 if (AOP_TYPE (result) == AOP_CRY)
4593 // if(size), result in bit
4594 // if(!size && ifx), conditional oper: if(left & right)
4595 symbol *tlbl = newiTempLabel (NULL);
4596 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4598 emitcode ("setb", "c");
4601 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4602 emitcode ("anl", "a,%s",
4603 aopGet (AOP (right), offset, FALSE, FALSE));
4605 if (AOP_TYPE(left)==AOP_ACC) {
4606 emitcode("mov", "b,a");
4607 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4608 emitcode("anl", "a,b");
4610 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4611 emitcode ("anl", "a,%s",
4612 aopGet (AOP (left), offset, FALSE, FALSE));
4615 emitcode ("jnz", "%05d$", tlbl->key + 100);
4621 emitcode ("", "%05d$:", tlbl->key + 100);
4625 jmpTrueOrFalse (ifx, tlbl);
4629 for (; (size--); offset++)
4632 // result = left & right
4633 if (AOP_TYPE (right) == AOP_LIT)
4635 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4637 aopPut (AOP (result),
4638 aopGet (AOP (left), offset, FALSE, FALSE),
4642 else if (bytelit == 0)
4644 aopPut (AOP (result), zero, offset);
4648 // faster than result <- left, anl result,right
4649 // and better if result is SFR
4650 if (AOP_TYPE (left) == AOP_ACC)
4651 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4654 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4655 emitcode ("anl", "a,%s",
4656 aopGet (AOP (left), offset, FALSE, FALSE));
4658 aopPut (AOP (result), "a", offset);
4664 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4665 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4666 freeAsmop (result, NULL, ic, TRUE);
4669 /*-----------------------------------------------------------------*/
4670 /* genOr - code for or */
4671 /*-----------------------------------------------------------------*/
4673 genOr (iCode * ic, iCode * ifx)
4675 operand *left, *right, *result;
4676 int size, offset = 0;
4677 unsigned long lit = 0L;
4679 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4680 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4681 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4684 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4686 AOP_TYPE (left), AOP_TYPE (right));
4687 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4689 AOP_SIZE (left), AOP_SIZE (right));
4692 /* if left is a literal & right is not then exchange them */
4693 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4694 AOP_NEEDSACC (left))
4696 operand *tmp = right;
4701 /* if result = right then exchange them */
4702 if (sameRegs (AOP (result), AOP (right)))
4704 operand *tmp = right;
4709 /* if right is bit then exchange them */
4710 if (AOP_TYPE (right) == AOP_CRY &&
4711 AOP_TYPE (left) != AOP_CRY)
4713 operand *tmp = right;
4717 if (AOP_TYPE (right) == AOP_LIT)
4718 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4720 size = AOP_SIZE (result);
4724 if (AOP_TYPE (left) == AOP_CRY)
4726 if (AOP_TYPE (right) == AOP_LIT)
4728 // c = bit & literal;
4731 // lit != 0 => result = 1
4732 if (AOP_TYPE (result) == AOP_CRY)
4735 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4737 continueIfTrue (ifx);
4740 emitcode ("setb", "c");
4744 // lit == 0 => result = left
4745 if (size && sameRegs (AOP (result), AOP (left)))
4747 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4752 if (AOP_TYPE (right) == AOP_CRY)
4755 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4756 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4761 symbol *tlbl = newiTempLabel (NULL);
4762 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4763 emitcode ("setb", "c");
4764 emitcode ("jb", "%s,%05d$",
4765 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4767 emitcode ("jnz", "%05d$", tlbl->key + 100);
4768 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4770 jmpTrueOrFalse (ifx, tlbl);
4776 emitcode ("", "%05d$:", tlbl->key + 100);
4785 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4786 genIfxJump (ifx, "c");
4790 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4791 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4792 if ((AOP_TYPE (right) == AOP_LIT) &&
4793 (AOP_TYPE (result) == AOP_CRY) &&
4794 (AOP_TYPE (left) != AOP_CRY))
4800 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4802 continueIfTrue (ifx);
4807 // lit = 0, result = boolean(left)
4809 emitcode ("setb", "c");
4813 symbol *tlbl = newiTempLabel (NULL);
4814 emitcode ("jnz", "%05d$", tlbl->key + 100);
4816 emitcode ("", "%05d$:", tlbl->key + 100);
4820 genIfxJump (ifx, "a");
4828 /* if left is same as result */
4829 if (sameRegs (AOP (result), AOP (left)))
4831 for (; size--; offset++)
4833 if (AOP_TYPE (right) == AOP_LIT)
4835 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4837 else if (IS_AOP_PREG (left))
4839 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4840 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4841 aopPut (AOP (result), "a", offset);
4844 emitcode ("orl", "%s,%s",
4845 aopGet (AOP (left), offset, FALSE, TRUE),
4846 aopGet (AOP (right), offset, FALSE, FALSE));
4850 if (AOP_TYPE (left) == AOP_ACC)
4851 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4854 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4855 if (IS_AOP_PREG (left))
4857 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4858 aopPut (AOP (result), "a", offset);
4861 emitcode ("orl", "%s,a",
4862 aopGet (AOP (left), offset, FALSE, TRUE));
4869 // left & result in different registers
4870 if (AOP_TYPE (result) == AOP_CRY)
4873 // if(size), result in bit
4874 // if(!size && ifx), conditional oper: if(left | right)
4875 symbol *tlbl = newiTempLabel (NULL);
4876 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4878 emitcode ("setb", "c");
4881 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4882 emitcode ("orl", "a,%s",
4883 aopGet (AOP (right), offset, FALSE, FALSE));
4885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4886 emitcode ("orl", "a,%s",
4887 aopGet (AOP (left), offset, FALSE, FALSE));
4889 emitcode ("jnz", "%05d$", tlbl->key + 100);
4895 emitcode ("", "%05d$:", tlbl->key + 100);
4899 jmpTrueOrFalse (ifx, tlbl);
4902 for (; (size--); offset++)
4905 // result = left & right
4906 if (AOP_TYPE (right) == AOP_LIT)
4908 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4910 aopPut (AOP (result),
4911 aopGet (AOP (left), offset, FALSE, FALSE),
4916 // faster than result <- left, anl result,right
4917 // and better if result is SFR
4918 if (AOP_TYPE (left) == AOP_ACC)
4919 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4922 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4923 emitcode ("orl", "a,%s",
4924 aopGet (AOP (left), offset, FALSE, FALSE));
4926 aopPut (AOP (result), "a", offset);
4931 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4933 freeAsmop (result, NULL, ic, TRUE);
4936 /*-----------------------------------------------------------------*/
4937 /* genXor - code for xclusive or */
4938 /*-----------------------------------------------------------------*/
4940 genXor (iCode * ic, iCode * ifx)
4942 operand *left, *right, *result;
4943 int size, offset = 0;
4944 unsigned long lit = 0L;
4946 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4947 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4948 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4951 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4953 AOP_TYPE (left), AOP_TYPE (right));
4954 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4956 AOP_SIZE (left), AOP_SIZE (right));
4959 /* if left is a literal & right is not ||
4960 if left needs acc & right does not */
4961 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4962 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4964 operand *tmp = right;
4969 /* if result = right then exchange them */
4970 if (sameRegs (AOP (result), AOP (right)))
4972 operand *tmp = right;
4977 /* if right is bit then exchange them */
4978 if (AOP_TYPE (right) == AOP_CRY &&
4979 AOP_TYPE (left) != AOP_CRY)
4981 operand *tmp = right;
4985 if (AOP_TYPE (right) == AOP_LIT)
4986 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4988 size = AOP_SIZE (result);
4992 if (AOP_TYPE (left) == AOP_CRY)
4994 if (AOP_TYPE (right) == AOP_LIT)
4996 // c = bit & literal;
4999 // lit>>1 != 0 => result = 1
5000 if (AOP_TYPE (result) == AOP_CRY)
5003 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5005 continueIfTrue (ifx);
5008 emitcode ("setb", "c");
5015 // lit == 0, result = left
5016 if (size && sameRegs (AOP (result), AOP (left)))
5018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5022 // lit == 1, result = not(left)
5023 if (size && sameRegs (AOP (result), AOP (left)))
5025 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5030 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5031 emitcode ("cpl", "c");
5040 symbol *tlbl = newiTempLabel (NULL);
5041 if (AOP_TYPE (right) == AOP_CRY)
5044 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5048 int sizer = AOP_SIZE (right);
5050 // if val>>1 != 0, result = 1
5051 emitcode ("setb", "c");
5054 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5056 // test the msb of the lsb
5057 emitcode ("anl", "a,#0xfe");
5058 emitcode ("jnz", "%05d$", tlbl->key + 100);
5062 emitcode ("rrc", "a");
5064 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5065 emitcode ("cpl", "c");
5066 emitcode ("", "%05d$:", (tlbl->key + 100));
5073 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5074 genIfxJump (ifx, "c");
5078 if (sameRegs (AOP (result), AOP (left)))
5080 /* if left is same as result */
5081 for (; size--; offset++)
5083 if (AOP_TYPE (right) == AOP_LIT)
5085 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5087 else if (IS_AOP_PREG (left))
5089 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5090 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5091 aopPut (AOP (result), "a", offset);
5094 emitcode ("xrl", "%s,%s",
5095 aopGet (AOP (left), offset, FALSE, TRUE),
5096 aopGet (AOP (right), offset, FALSE, FALSE));
5100 if (AOP_TYPE (left) == AOP_ACC)
5101 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5104 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5105 if (IS_AOP_PREG (left))
5107 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5108 aopPut (AOP (result), "a", offset);
5111 emitcode ("xrl", "%s,a",
5112 aopGet (AOP (left), offset, FALSE, TRUE));
5119 // left & result in different registers
5120 if (AOP_TYPE (result) == AOP_CRY)
5123 // if(size), result in bit
5124 // if(!size && ifx), conditional oper: if(left ^ right)
5125 symbol *tlbl = newiTempLabel (NULL);
5126 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5128 emitcode ("setb", "c");
5131 if ((AOP_TYPE (right) == AOP_LIT) &&
5132 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5134 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5138 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5139 emitcode ("xrl", "a,%s",
5140 aopGet (AOP (right), offset, FALSE, FALSE));
5142 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5143 emitcode ("xrl", "a,%s",
5144 aopGet (AOP (left), offset, FALSE, FALSE));
5147 emitcode ("jnz", "%05d$", tlbl->key + 100);
5153 emitcode ("", "%05d$:", tlbl->key + 100);
5157 jmpTrueOrFalse (ifx, tlbl);
5160 for (; (size--); offset++)
5163 // result = left & right
5164 if (AOP_TYPE (right) == AOP_LIT)
5166 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5168 aopPut (AOP (result),
5169 aopGet (AOP (left), offset, FALSE, FALSE),
5174 // faster than result <- left, anl result,right
5175 // and better if result is SFR
5176 if (AOP_TYPE (left) == AOP_ACC)
5177 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5180 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5181 emitcode ("xrl", "a,%s",
5182 aopGet (AOP (left), offset, FALSE, TRUE));
5184 aopPut (AOP (result), "a", offset);
5189 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5190 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5191 freeAsmop (result, NULL, ic, TRUE);
5194 /*-----------------------------------------------------------------*/
5195 /* genInline - write the inline code out */
5196 /*-----------------------------------------------------------------*/
5198 genInline (iCode * ic)
5200 char *buffer, *bp, *bp1;
5202 _G.inLine += (!options.asmpeep);
5204 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5205 strcpy (buffer, IC_INLINE (ic));
5207 /* emit each line as a code */
5232 /* emitcode("",buffer); */
5233 _G.inLine -= (!options.asmpeep);
5236 /*-----------------------------------------------------------------*/
5237 /* genRRC - rotate right with carry */
5238 /*-----------------------------------------------------------------*/
5242 operand *left, *result;
5243 int size, offset = 0;
5246 /* rotate right with carry */
5247 left = IC_LEFT (ic);
5248 result = IC_RESULT (ic);
5249 aopOp (left, ic, FALSE);
5250 aopOp (result, ic, FALSE);
5252 /* move it to the result */
5253 size = AOP_SIZE (result);
5258 l = aopGet (AOP (left), offset, FALSE, FALSE);
5260 emitcode ("rrc", "a");
5261 if (AOP_SIZE (result) > 1)
5262 aopPut (AOP (result), "a", offset--);
5264 /* now we need to put the carry into the
5265 highest order byte of the result */
5266 if (AOP_SIZE (result) > 1)
5268 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5271 emitcode ("mov", "acc.7,c");
5272 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5273 freeAsmop (left, NULL, ic, TRUE);
5274 freeAsmop (result, NULL, ic, TRUE);
5277 /*-----------------------------------------------------------------*/
5278 /* genRLC - generate code for rotate left with carry */
5279 /*-----------------------------------------------------------------*/
5283 operand *left, *result;
5284 int size, offset = 0;
5287 /* rotate right with carry */
5288 left = IC_LEFT (ic);
5289 result = IC_RESULT (ic);
5290 aopOp (left, ic, FALSE);
5291 aopOp (result, ic, FALSE);
5293 /* move it to the result */
5294 size = AOP_SIZE (result);
5298 l = aopGet (AOP (left), offset, FALSE, FALSE);
5300 emitcode ("add", "a,acc");
5301 if (AOP_SIZE (result) > 1)
5302 aopPut (AOP (result), "a", offset++);
5305 l = aopGet (AOP (left), offset, FALSE, FALSE);
5307 emitcode ("rlc", "a");
5308 if (AOP_SIZE (result) > 1)
5309 aopPut (AOP (result), "a", offset++);
5312 /* now we need to put the carry into the
5313 highest order byte of the result */
5314 if (AOP_SIZE (result) > 1)
5316 l = aopGet (AOP (result), 0, FALSE, FALSE);
5319 emitcode ("mov", "acc.0,c");
5320 aopPut (AOP (result), "a", 0);
5321 freeAsmop (left, NULL, ic, TRUE);
5322 freeAsmop (result, NULL, ic, TRUE);
5325 /*-----------------------------------------------------------------*/
5326 /* genGetHbit - generates code get highest order bit */
5327 /*-----------------------------------------------------------------*/
5329 genGetHbit (iCode * ic)
5331 operand *left, *result;
5332 left = IC_LEFT (ic);
5333 result = IC_RESULT (ic);
5334 aopOp (left, ic, FALSE);
5335 aopOp (result, ic, FALSE);
5337 /* get the highest order byte into a */
5338 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5339 if (AOP_TYPE (result) == AOP_CRY)
5341 emitcode ("rlc", "a");
5346 emitcode ("rl", "a");
5347 emitcode ("anl", "a,#0x01");
5352 freeAsmop (left, NULL, ic, TRUE);
5353 freeAsmop (result, NULL, ic, TRUE);
5356 /*-----------------------------------------------------------------*/
5357 /* AccRol - rotate left accumulator by known count */
5358 /*-----------------------------------------------------------------*/
5360 AccRol (int shCount)
5362 shCount &= 0x0007; // shCount : 0..7
5369 emitcode ("rl", "a");
5372 emitcode ("rl", "a");
5373 emitcode ("rl", "a");
5376 emitcode ("swap", "a");
5377 emitcode ("rr", "a");
5380 emitcode ("swap", "a");
5383 emitcode ("swap", "a");
5384 emitcode ("rl", "a");
5387 emitcode ("rr", "a");
5388 emitcode ("rr", "a");
5391 emitcode ("rr", "a");
5396 /*-----------------------------------------------------------------*/
5397 /* AccLsh - left shift accumulator by known count */
5398 /*-----------------------------------------------------------------*/
5400 AccLsh (int shCount)
5405 emitcode ("add", "a,acc");
5406 else if (shCount == 2)
5408 emitcode ("add", "a,acc");
5409 emitcode ("add", "a,acc");
5413 /* rotate left accumulator */
5415 /* and kill the lower order bits */
5416 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5421 /*-----------------------------------------------------------------*/
5422 /* AccRsh - right shift accumulator by known count */
5423 /*-----------------------------------------------------------------*/
5425 AccRsh (int shCount)
5432 emitcode ("rrc", "a");
5436 /* rotate right accumulator */
5437 AccRol (8 - shCount);
5438 /* and kill the higher order bits */
5439 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5444 /*-----------------------------------------------------------------*/
5445 /* AccSRsh - signed right shift accumulator by known count */
5446 /*-----------------------------------------------------------------*/
5448 AccSRsh (int shCount)
5455 emitcode ("mov", "c,acc.7");
5456 emitcode ("rrc", "a");
5458 else if (shCount == 2)
5460 emitcode ("mov", "c,acc.7");
5461 emitcode ("rrc", "a");
5462 emitcode ("mov", "c,acc.7");
5463 emitcode ("rrc", "a");
5467 tlbl = newiTempLabel (NULL);
5468 /* rotate right accumulator */
5469 AccRol (8 - shCount);
5470 /* and kill the higher order bits */
5471 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5472 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5473 emitcode ("orl", "a,#0x%02x",
5474 (unsigned char) ~SRMask[shCount]);
5475 emitcode ("", "%05d$:", tlbl->key + 100);
5480 /*-----------------------------------------------------------------*/
5481 /* shiftR1Left2Result - shift right one byte from left to result */
5482 /*-----------------------------------------------------------------*/
5484 shiftR1Left2Result (operand * left, int offl,
5485 operand * result, int offr,
5486 int shCount, int sign)
5488 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5489 /* shift right accumulator */
5494 aopPut (AOP (result), "a", offr);
5497 /*-----------------------------------------------------------------*/
5498 /* shiftL1Left2Result - shift left one byte from left to result */
5499 /*-----------------------------------------------------------------*/
5501 shiftL1Left2Result (operand * left, int offl,
5502 operand * result, int offr, int shCount)
5505 l = aopGet (AOP (left), offl, FALSE, FALSE);
5507 /* shift left accumulator */
5509 aopPut (AOP (result), "a", offr);
5512 /*-----------------------------------------------------------------*/
5513 /* movLeft2Result - move byte from left to result */
5514 /*-----------------------------------------------------------------*/
5516 movLeft2Result (operand * left, int offl,
5517 operand * result, int offr, int sign)
5520 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5522 l = aopGet (AOP (left), offl, FALSE, FALSE);
5524 if (*l == '@' && (IS_AOP_PREG (result)))
5526 emitcode ("mov", "a,%s", l);
5527 aopPut (AOP (result), "a", offr);
5532 aopPut (AOP (result), l, offr);
5535 /* MSB sign in acc.7 ! */
5536 if (getDataSize (left) == offl + 1)
5538 emitcode ("mov", "a,%s", l);
5539 aopPut (AOP (result), "a", offr);
5546 /*-----------------------------------------------------------------*/
5547 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5548 /*-----------------------------------------------------------------*/
5552 emitcode ("rrc", "a");
5553 emitcode ("xch", "a,%s", x);
5554 emitcode ("rrc", "a");
5555 emitcode ("xch", "a,%s", x);
5558 /*-----------------------------------------------------------------*/
5559 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5560 /*-----------------------------------------------------------------*/
5564 emitcode ("xch", "a,%s", x);
5565 emitcode ("rlc", "a");
5566 emitcode ("xch", "a,%s", x);
5567 emitcode ("rlc", "a");
5570 /*-----------------------------------------------------------------*/
5571 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5572 /*-----------------------------------------------------------------*/
5576 emitcode ("xch", "a,%s", x);
5577 emitcode ("add", "a,acc");
5578 emitcode ("xch", "a,%s", x);
5579 emitcode ("rlc", "a");
5582 /*-----------------------------------------------------------------*/
5583 /* AccAXLsh - left shift a:x by known count (0..7) */
5584 /*-----------------------------------------------------------------*/
5586 AccAXLsh (char *x, int shCount)
5601 case 5: // AAAAABBB:CCCCCDDD
5603 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5605 emitcode ("anl", "a,#0x%02x",
5606 SLMask[shCount]); // BBB00000:CCCCCDDD
5608 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5610 AccRol (shCount); // DDDCCCCC:BBB00000
5612 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5614 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5616 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5618 emitcode ("anl", "a,#0x%02x",
5619 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5621 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5623 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5626 case 6: // AAAAAABB:CCCCCCDD
5627 emitcode ("anl", "a,#0x%02x",
5628 SRMask[shCount]); // 000000BB:CCCCCCDD
5629 emitcode ("mov", "c,acc.0"); // c = B
5630 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5632 AccAXRrl1 (x); // BCCCCCCD:D000000B
5633 AccAXRrl1 (x); // BBCCCCCC:DD000000
5635 emitcode("rrc","a");
5636 emitcode("xch","a,%s", x);
5637 emitcode("rrc","a");
5638 emitcode("mov","c,acc.0"); //<< get correct bit
5639 emitcode("xch","a,%s", x);
5641 emitcode("rrc","a");
5642 emitcode("xch","a,%s", x);
5643 emitcode("rrc","a");
5644 emitcode("xch","a,%s", x);
5647 case 7: // a:x <<= 7
5649 emitcode ("anl", "a,#0x%02x",
5650 SRMask[shCount]); // 0000000B:CCCCCCCD
5652 emitcode ("mov", "c,acc.0"); // c = B
5654 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5656 AccAXRrl1 (x); // BCCCCCCC:D0000000
5664 /*-----------------------------------------------------------------*/
5665 /* AccAXRsh - right shift a:x known count (0..7) */
5666 /*-----------------------------------------------------------------*/
5668 AccAXRsh (char *x, int shCount)
5676 AccAXRrl1 (x); // 0->a:x
5681 AccAXRrl1 (x); // 0->a:x
5684 AccAXRrl1 (x); // 0->a:x
5689 case 5: // AAAAABBB:CCCCCDDD = a:x
5691 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5693 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5695 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5697 emitcode ("anl", "a,#0x%02x",
5698 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5700 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5702 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5704 emitcode ("anl", "a,#0x%02x",
5705 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5707 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5709 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5711 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5714 case 6: // AABBBBBB:CCDDDDDD
5716 emitcode ("mov", "c,acc.7");
5717 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5719 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5721 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5723 emitcode ("anl", "a,#0x%02x",
5724 SRMask[shCount]); // 000000AA:BBBBBBCC
5727 case 7: // ABBBBBBB:CDDDDDDD
5729 emitcode ("mov", "c,acc.7"); // c = A
5731 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5733 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5735 emitcode ("anl", "a,#0x%02x",
5736 SRMask[shCount]); // 0000000A:BBBBBBBC
5744 /*-----------------------------------------------------------------*/
5745 /* AccAXRshS - right shift signed a:x known count (0..7) */
5746 /*-----------------------------------------------------------------*/
5748 AccAXRshS (char *x, int shCount)
5756 emitcode ("mov", "c,acc.7");
5757 AccAXRrl1 (x); // s->a:x
5761 emitcode ("mov", "c,acc.7");
5762 AccAXRrl1 (x); // s->a:x
5764 emitcode ("mov", "c,acc.7");
5765 AccAXRrl1 (x); // s->a:x
5770 case 5: // AAAAABBB:CCCCCDDD = a:x
5772 tlbl = newiTempLabel (NULL);
5773 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5775 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5777 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5779 emitcode ("anl", "a,#0x%02x",
5780 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5782 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5784 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5786 emitcode ("anl", "a,#0x%02x",
5787 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5789 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5791 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5793 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5795 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5796 emitcode ("orl", "a,#0x%02x",
5797 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5799 emitcode ("", "%05d$:", tlbl->key + 100);
5800 break; // SSSSAAAA:BBBCCCCC
5802 case 6: // AABBBBBB:CCDDDDDD
5804 tlbl = newiTempLabel (NULL);
5805 emitcode ("mov", "c,acc.7");
5806 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5808 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5810 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5812 emitcode ("anl", "a,#0x%02x",
5813 SRMask[shCount]); // 000000AA:BBBBBBCC
5815 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5816 emitcode ("orl", "a,#0x%02x",
5817 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5819 emitcode ("", "%05d$:", tlbl->key + 100);
5821 case 7: // ABBBBBBB:CDDDDDDD
5823 tlbl = newiTempLabel (NULL);
5824 emitcode ("mov", "c,acc.7"); // c = A
5826 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5828 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5830 emitcode ("anl", "a,#0x%02x",
5831 SRMask[shCount]); // 0000000A:BBBBBBBC
5833 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5834 emitcode ("orl", "a,#0x%02x",
5835 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5837 emitcode ("", "%05d$:", tlbl->key + 100);
5844 /*-----------------------------------------------------------------*/
5845 /* shiftL2Left2Result - shift left two bytes from left to result */
5846 /*-----------------------------------------------------------------*/
5848 shiftL2Left2Result (operand * left, int offl,
5849 operand * result, int offr, int shCount)
5851 if (sameRegs (AOP (result), AOP (left)) &&
5852 ((offl + MSB16) == offr))
5854 /* don't crash result[offr] */
5855 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5856 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5860 movLeft2Result (left, offl, result, offr, 0);
5861 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5863 /* ax << shCount (x = lsb(result)) */
5864 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5865 aopPut (AOP (result), "a", offr + MSB16);
5869 /*-----------------------------------------------------------------*/
5870 /* shiftR2Left2Result - shift right two bytes from left to result */
5871 /*-----------------------------------------------------------------*/
5873 shiftR2Left2Result (operand * left, int offl,
5874 operand * result, int offr,
5875 int shCount, int sign)
5877 if (sameRegs (AOP (result), AOP (left)) &&
5878 ((offl + MSB16) == offr))
5880 /* don't crash result[offr] */
5881 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5882 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5886 movLeft2Result (left, offl, result, offr, 0);
5887 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5889 /* a:x >> shCount (x = lsb(result)) */
5891 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5893 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5894 if (getDataSize (result) > 1)
5895 aopPut (AOP (result), "a", offr + MSB16);
5898 /*-----------------------------------------------------------------*/
5899 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5900 /*-----------------------------------------------------------------*/
5902 shiftLLeftOrResult (operand * left, int offl,
5903 operand * result, int offr, int shCount)
5905 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5906 /* shift left accumulator */
5908 /* or with result */
5909 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5910 /* back to result */
5911 aopPut (AOP (result), "a", offr);
5914 /*-----------------------------------------------------------------*/
5915 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5916 /*-----------------------------------------------------------------*/
5918 shiftRLeftOrResult (operand * left, int offl,
5919 operand * result, int offr, int shCount)
5921 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5922 /* shift right accumulator */
5924 /* or with result */
5925 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5926 /* back to result */
5927 aopPut (AOP (result), "a", offr);
5930 /*-----------------------------------------------------------------*/
5931 /* genlshOne - left shift a one byte quantity by known count */
5932 /*-----------------------------------------------------------------*/
5934 genlshOne (operand * result, operand * left, int shCount)
5936 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5939 /*-----------------------------------------------------------------*/
5940 /* genlshTwo - left shift two bytes by known amount != 0 */
5941 /*-----------------------------------------------------------------*/
5943 genlshTwo (operand * result, operand * left, int shCount)
5947 size = getDataSize (result);
5949 /* if shCount >= 8 */
5957 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5959 movLeft2Result (left, LSB, result, MSB16, 0);
5961 aopPut (AOP (result), zero, LSB);
5964 /* 1 <= shCount <= 7 */
5968 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5970 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5974 /*-----------------------------------------------------------------*/
5975 /* shiftLLong - shift left one long from left to result */
5976 /* offl = LSB or MSB16 */
5977 /*-----------------------------------------------------------------*/
5979 shiftLLong (operand * left, operand * result, int offr)
5982 int size = AOP_SIZE (result);
5984 if (size >= LSB + offr)
5986 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5988 emitcode ("add", "a,acc");
5989 if (sameRegs (AOP (left), AOP (result)) &&
5990 size >= MSB16 + offr && offr != LSB)
5991 emitcode ("xch", "a,%s",
5992 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5994 aopPut (AOP (result), "a", LSB + offr);
5997 if (size >= MSB16 + offr)
5999 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6001 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6004 emitcode ("rlc", "a");
6005 if (sameRegs (AOP (left), AOP (result)) &&
6006 size >= MSB24 + offr && offr != LSB)
6007 emitcode ("xch", "a,%s",
6008 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6010 aopPut (AOP (result), "a", MSB16 + offr);
6013 if (size >= MSB24 + offr)
6015 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6017 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6020 emitcode ("rlc", "a");
6021 if (sameRegs (AOP (left), AOP (result)) &&
6022 size >= MSB32 + offr && offr != LSB)
6023 emitcode ("xch", "a,%s",
6024 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6026 aopPut (AOP (result), "a", MSB24 + offr);
6029 if (size > MSB32 + offr)
6031 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6033 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6036 emitcode ("rlc", "a");
6037 aopPut (AOP (result), "a", MSB32 + offr);
6040 aopPut (AOP (result), zero, LSB);
6043 /*-----------------------------------------------------------------*/
6044 /* genlshFour - shift four byte by a known amount != 0 */
6045 /*-----------------------------------------------------------------*/
6047 genlshFour (operand * result, operand * left, int shCount)
6051 size = AOP_SIZE (result);
6053 /* if shifting more that 3 bytes */
6058 /* lowest order of left goes to the highest
6059 order of the destination */
6060 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6062 movLeft2Result (left, LSB, result, MSB32, 0);
6063 aopPut (AOP (result), zero, LSB);
6064 aopPut (AOP (result), zero, MSB16);
6065 aopPut (AOP (result), zero, MSB24);
6069 /* more than two bytes */
6070 else if (shCount >= 16)
6072 /* lower order two bytes goes to higher order two bytes */
6074 /* if some more remaining */
6076 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6079 movLeft2Result (left, MSB16, result, MSB32, 0);
6080 movLeft2Result (left, LSB, result, MSB24, 0);
6082 aopPut (AOP (result), zero, MSB16);
6083 aopPut (AOP (result), zero, LSB);
6087 /* if more than 1 byte */
6088 else if (shCount >= 8)
6090 /* lower order three bytes goes to higher order three bytes */
6095 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6097 movLeft2Result (left, LSB, result, MSB16, 0);
6103 movLeft2Result (left, MSB24, result, MSB32, 0);
6104 movLeft2Result (left, MSB16, result, MSB24, 0);
6105 movLeft2Result (left, LSB, result, MSB16, 0);
6106 aopPut (AOP (result), zero, LSB);
6108 else if (shCount == 1)
6109 shiftLLong (left, result, MSB16);
6112 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6113 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6114 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6115 aopPut (AOP (result), zero, LSB);
6120 /* 1 <= shCount <= 7 */
6121 else if (shCount <= 2)
6123 shiftLLong (left, result, LSB);
6125 shiftLLong (result, result, LSB);
6127 /* 3 <= shCount <= 7, optimize */
6130 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6131 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6132 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6136 /*-----------------------------------------------------------------*/
6137 /* genLeftShiftLiteral - left shifting by known count */
6138 /*-----------------------------------------------------------------*/
6140 genLeftShiftLiteral (operand * left,
6145 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6148 freeAsmop (right, NULL, ic, TRUE);
6150 aopOp (left, ic, FALSE);
6151 aopOp (result, ic, FALSE);
6153 size = getSize (operandType (result));
6156 emitcode ("; shift left ", "result %d, left %d", size,
6160 /* I suppose that the left size >= result size */
6165 movLeft2Result (left, size, result, size, 0);
6169 else if (shCount >= (size * 8))
6171 aopPut (AOP (result), zero, size);
6177 genlshOne (result, left, shCount);
6181 genlshTwo (result, left, shCount);
6185 genlshFour (result, left, shCount);
6188 fprintf(stderr, "*** ack! mystery literal shift!\n");
6192 freeAsmop (left, NULL, ic, TRUE);
6193 freeAsmop (result, NULL, ic, TRUE);
6196 /*-----------------------------------------------------------------*/
6197 /* genLeftShift - generates code for left shifting */
6198 /*-----------------------------------------------------------------*/
6200 genLeftShift (iCode * ic)
6202 operand *left, *right, *result;
6205 symbol *tlbl, *tlbl1;
6207 right = IC_RIGHT (ic);
6208 left = IC_LEFT (ic);
6209 result = IC_RESULT (ic);
6211 aopOp (right, ic, FALSE);
6213 /* if the shift count is known then do it
6214 as efficiently as possible */
6215 if (AOP_TYPE (right) == AOP_LIT)
6217 genLeftShiftLiteral (left, right, result, ic);
6221 /* shift count is unknown then we have to form
6222 a loop get the loop count in B : Note: we take
6223 only the lower order byte since shifting
6224 more that 32 bits make no sense anyway, ( the
6225 largest size of an object can be only 32 bits ) */
6227 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6228 emitcode ("inc", "b");
6229 freeAsmop (right, NULL, ic, TRUE);
6230 aopOp (left, ic, FALSE);
6231 aopOp (result, ic, FALSE);
6233 /* now move the left to the result if they are not the
6235 if (!sameRegs (AOP (left), AOP (result)) &&
6236 AOP_SIZE (result) > 1)
6239 size = AOP_SIZE (result);
6243 l = aopGet (AOP (left), offset, FALSE, TRUE);
6244 if (*l == '@' && (IS_AOP_PREG (result)))
6247 emitcode ("mov", "a,%s", l);
6248 aopPut (AOP (result), "a", offset);
6251 aopPut (AOP (result), l, offset);
6256 tlbl = newiTempLabel (NULL);
6257 size = AOP_SIZE (result);
6259 tlbl1 = newiTempLabel (NULL);
6261 /* if it is only one byte then */
6264 symbol *tlbl1 = newiTempLabel (NULL);
6266 l = aopGet (AOP (left), 0, FALSE, FALSE);
6268 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6269 emitcode ("", "%05d$:", tlbl->key + 100);
6270 emitcode ("add", "a,acc");
6271 emitcode ("", "%05d$:", tlbl1->key + 100);
6272 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6273 aopPut (AOP (result), "a", 0);
6277 reAdjustPreg (AOP (result));
6279 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6280 emitcode ("", "%05d$:", tlbl->key + 100);
6281 l = aopGet (AOP (result), offset, FALSE, FALSE);
6283 emitcode ("add", "a,acc");
6284 aopPut (AOP (result), "a", offset++);
6287 l = aopGet (AOP (result), offset, FALSE, FALSE);
6289 emitcode ("rlc", "a");
6290 aopPut (AOP (result), "a", offset++);
6292 reAdjustPreg (AOP (result));
6294 emitcode ("", "%05d$:", tlbl1->key + 100);
6295 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6297 freeAsmop (left, NULL, ic, TRUE);
6298 freeAsmop (result, NULL, ic, TRUE);
6301 /*-----------------------------------------------------------------*/
6302 /* genrshOne - right shift a one byte quantity by known count */
6303 /*-----------------------------------------------------------------*/
6305 genrshOne (operand * result, operand * left,
6306 int shCount, int sign)
6308 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6311 /*-----------------------------------------------------------------*/
6312 /* genrshTwo - right shift two bytes by known amount != 0 */
6313 /*-----------------------------------------------------------------*/
6315 genrshTwo (operand * result, operand * left,
6316 int shCount, int sign)
6318 /* if shCount >= 8 */
6323 shiftR1Left2Result (left, MSB16, result, LSB,
6326 movLeft2Result (left, MSB16, result, LSB, sign);
6327 addSign (result, MSB16, sign);
6330 /* 1 <= shCount <= 7 */
6332 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6335 /*-----------------------------------------------------------------*/
6336 /* shiftRLong - shift right one long from left to result */
6337 /* offl = LSB or MSB16 */
6338 /*-----------------------------------------------------------------*/
6340 shiftRLong (operand * left, int offl,
6341 operand * result, int sign)
6343 int isSameRegs=sameRegs(AOP(left),AOP(result));
6345 if (isSameRegs && offl>1) {
6346 // we are in big trouble, but this shouldn't happen
6347 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6350 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6355 emitcode ("rlc", "a");
6356 emitcode ("subb", "a,acc");
6357 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6359 aopPut (AOP(result), zero, MSB32);
6364 emitcode ("clr", "c");
6366 emitcode ("mov", "c,acc.7");
6369 emitcode ("rrc", "a");
6371 if (isSameRegs && offl==MSB16) {
6372 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6374 aopPut (AOP (result), "a", MSB32);
6375 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6378 emitcode ("rrc", "a");
6379 if (isSameRegs && offl==1) {
6380 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6382 aopPut (AOP (result), "a", MSB24);
6383 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6385 emitcode ("rrc", "a");
6386 aopPut (AOP (result), "a", MSB16 - offl);
6390 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6391 emitcode ("rrc", "a");
6392 aopPut (AOP (result), "a", LSB);
6396 /*-----------------------------------------------------------------*/
6397 /* genrshFour - shift four byte by a known amount != 0 */
6398 /*-----------------------------------------------------------------*/
6400 genrshFour (operand * result, operand * left,
6401 int shCount, int sign)
6403 /* if shifting more that 3 bytes */
6408 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6410 movLeft2Result (left, MSB32, result, LSB, sign);
6411 addSign (result, MSB16, sign);
6413 else if (shCount >= 16)
6417 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6420 movLeft2Result (left, MSB24, result, LSB, 0);
6421 movLeft2Result (left, MSB32, result, MSB16, sign);
6423 addSign (result, MSB24, sign);
6425 else if (shCount >= 8)
6429 shiftRLong (left, MSB16, result, sign);
6430 else if (shCount == 0)
6432 movLeft2Result (left, MSB16, result, LSB, 0);
6433 movLeft2Result (left, MSB24, result, MSB16, 0);
6434 movLeft2Result (left, MSB32, result, MSB24, sign);
6435 addSign (result, MSB32, sign);
6439 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6440 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6441 /* the last shift is signed */
6442 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6443 addSign (result, MSB32, sign);
6447 { /* 1 <= shCount <= 7 */
6450 shiftRLong (left, LSB, result, sign);
6452 shiftRLong (result, LSB, result, sign);
6456 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6457 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6458 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6463 /*-----------------------------------------------------------------*/
6464 /* genRightShiftLiteral - right shifting by known count */
6465 /*-----------------------------------------------------------------*/
6467 genRightShiftLiteral (operand * left,
6473 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6476 freeAsmop (right, NULL, ic, TRUE);
6478 aopOp (left, ic, FALSE);
6479 aopOp (result, ic, FALSE);
6482 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6486 size = getDataSize (left);
6487 /* test the LEFT size !!! */
6489 /* I suppose that the left size >= result size */
6492 size = getDataSize (result);
6494 movLeft2Result (left, size, result, size, 0);
6497 else if (shCount >= (size * 8))
6500 /* get sign in acc.7 */
6501 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6502 addSign (result, LSB, sign);
6509 genrshOne (result, left, shCount, sign);
6513 genrshTwo (result, left, shCount, sign);
6517 genrshFour (result, left, shCount, sign);
6523 freeAsmop (left, NULL, ic, TRUE);
6524 freeAsmop (result, NULL, ic, TRUE);
6528 /*-----------------------------------------------------------------*/
6529 /* genSignedRightShift - right shift of signed number */
6530 /*-----------------------------------------------------------------*/
6532 genSignedRightShift (iCode * ic)
6534 operand *right, *left, *result;
6537 symbol *tlbl, *tlbl1;
6539 /* we do it the hard way put the shift count in b
6540 and loop thru preserving the sign */
6542 right = IC_RIGHT (ic);
6543 left = IC_LEFT (ic);
6544 result = IC_RESULT (ic);
6546 aopOp (right, ic, FALSE);
6549 if (AOP_TYPE (right) == AOP_LIT)
6551 genRightShiftLiteral (left, right, result, ic, 1);
6554 /* shift count is unknown then we have to form
6555 a loop get the loop count in B : Note: we take
6556 only the lower order byte since shifting
6557 more that 32 bits make no sense anyway, ( the
6558 largest size of an object can be only 32 bits ) */
6560 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6561 emitcode ("inc", "b");
6562 freeAsmop (right, NULL, ic, TRUE);
6563 aopOp (left, ic, FALSE);
6564 aopOp (result, ic, FALSE);
6566 /* now move the left to the result if they are not the
6568 if (!sameRegs (AOP (left), AOP (result)) &&
6569 AOP_SIZE (result) > 1)
6572 size = AOP_SIZE (result);
6576 l = aopGet (AOP (left), offset, FALSE, TRUE);
6577 if (*l == '@' && IS_AOP_PREG (result))
6580 emitcode ("mov", "a,%s", l);
6581 aopPut (AOP (result), "a", offset);
6584 aopPut (AOP (result), l, offset);
6589 /* mov the highest order bit to OVR */
6590 tlbl = newiTempLabel (NULL);
6591 tlbl1 = newiTempLabel (NULL);
6593 size = AOP_SIZE (result);
6595 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6596 emitcode ("rlc", "a");
6597 emitcode ("mov", "ov,c");
6598 /* if it is only one byte then */
6601 l = aopGet (AOP (left), 0, FALSE, FALSE);
6603 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6604 emitcode ("", "%05d$:", tlbl->key + 100);
6605 emitcode ("mov", "c,ov");
6606 emitcode ("rrc", "a");
6607 emitcode ("", "%05d$:", tlbl1->key + 100);
6608 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6609 aopPut (AOP (result), "a", 0);
6613 reAdjustPreg (AOP (result));
6614 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6615 emitcode ("", "%05d$:", tlbl->key + 100);
6616 emitcode ("mov", "c,ov");
6619 l = aopGet (AOP (result), offset, FALSE, FALSE);
6621 emitcode ("rrc", "a");
6622 aopPut (AOP (result), "a", offset--);
6624 reAdjustPreg (AOP (result));
6625 emitcode ("", "%05d$:", tlbl1->key + 100);
6626 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6629 freeAsmop (left, NULL, ic, TRUE);
6630 freeAsmop (result, NULL, ic, TRUE);
6633 /*-----------------------------------------------------------------*/
6634 /* genRightShift - generate code for right shifting */
6635 /*-----------------------------------------------------------------*/
6637 genRightShift (iCode * ic)
6639 operand *right, *left, *result;
6643 symbol *tlbl, *tlbl1;
6645 /* if signed then we do it the hard way preserve the
6646 sign bit moving it inwards */
6647 retype = getSpec (operandType (IC_RESULT (ic)));
6649 if (!SPEC_USIGN (retype))
6651 genSignedRightShift (ic);
6655 /* signed & unsigned types are treated the same : i.e. the
6656 signed is NOT propagated inwards : quoting from the
6657 ANSI - standard : "for E1 >> E2, is equivalent to division
6658 by 2**E2 if unsigned or if it has a non-negative value,
6659 otherwise the result is implementation defined ", MY definition
6660 is that the sign does not get propagated */
6662 right = IC_RIGHT (ic);
6663 left = IC_LEFT (ic);
6664 result = IC_RESULT (ic);
6666 aopOp (right, ic, FALSE);
6668 /* if the shift count is known then do it
6669 as efficiently as possible */
6670 if (AOP_TYPE (right) == AOP_LIT)
6672 genRightShiftLiteral (left, right, result, ic, 0);
6676 /* shift count is unknown then we have to form
6677 a loop get the loop count in B : Note: we take
6678 only the lower order byte since shifting
6679 more that 32 bits make no sense anyway, ( the
6680 largest size of an object can be only 32 bits ) */
6682 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6683 emitcode ("inc", "b");
6684 freeAsmop (right, NULL, ic, TRUE);
6685 aopOp (left, ic, FALSE);
6686 aopOp (result, ic, FALSE);
6688 /* now move the left to the result if they are not the
6690 if (!sameRegs (AOP (left), AOP (result)) &&
6691 AOP_SIZE (result) > 1)
6694 size = AOP_SIZE (result);
6698 l = aopGet (AOP (left), offset, FALSE, TRUE);
6699 if (*l == '@' && IS_AOP_PREG (result))
6702 emitcode ("mov", "a,%s", l);
6703 aopPut (AOP (result), "a", offset);
6706 aopPut (AOP (result), l, offset);
6711 tlbl = newiTempLabel (NULL);
6712 tlbl1 = newiTempLabel (NULL);
6713 size = AOP_SIZE (result);
6716 /* if it is only one byte then */
6719 l = aopGet (AOP (left), 0, FALSE, FALSE);
6721 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6722 emitcode ("", "%05d$:", tlbl->key + 100);
6724 emitcode ("rrc", "a");
6725 emitcode ("", "%05d$:", tlbl1->key + 100);
6726 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6727 aopPut (AOP (result), "a", 0);
6731 reAdjustPreg (AOP (result));
6732 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6733 emitcode ("", "%05d$:", tlbl->key + 100);
6737 l = aopGet (AOP (result), offset, FALSE, FALSE);
6739 emitcode ("rrc", "a");
6740 aopPut (AOP (result), "a", offset--);
6742 reAdjustPreg (AOP (result));
6744 emitcode ("", "%05d$:", tlbl1->key + 100);
6745 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6748 freeAsmop (left, NULL, ic, TRUE);
6749 freeAsmop (result, NULL, ic, TRUE);
6752 /*-----------------------------------------------------------------*/
6753 /* genUnpackBits - generates code for unpacking bits */
6754 /*-----------------------------------------------------------------*/
6756 genUnpackBits (operand * result, char *rname, int ptype)
6764 etype = getSpec (operandType (result));
6765 rsize = getSize (operandType (result));
6766 /* read the first byte */
6772 emitcode ("mov", "a,@%s", rname);
6776 emitcode ("movx", "a,@%s", rname);
6780 emitcode ("movx", "a,@dptr");
6784 emitcode ("clr", "a");
6785 emitcode ("movc", "a,%s", "@a+dptr");
6789 emitcode ("lcall", "__gptrget");
6793 rlen = SPEC_BLEN (etype);
6795 /* if we have bitdisplacement then it fits */
6796 /* into this byte completely or if length is */
6797 /* less than a byte */
6798 if ((shCnt = SPEC_BSTR (etype)) ||
6799 (SPEC_BLEN (etype) <= 8))
6802 /* shift right acc */
6805 emitcode ("anl", "a,#0x%02x",
6806 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6807 aopPut (AOP (result), "a", offset++);
6811 /* bit field did not fit in a byte */
6812 aopPut (AOP (result), "a", offset++);
6821 emitcode ("inc", "%s", rname);
6822 emitcode ("mov", "a,@%s", rname);
6826 emitcode ("inc", "%s", rname);
6827 emitcode ("movx", "a,@%s", rname);
6831 emitcode ("inc", "dptr");
6832 emitcode ("movx", "a,@dptr");
6836 emitcode ("clr", "a");
6837 emitcode ("inc", "dptr");
6838 emitcode ("movc", "a", "@a+dptr");
6842 emitcode ("inc", "dptr");
6843 emitcode ("lcall", "__gptrget");
6848 /* if we are done */
6852 aopPut (AOP (result), "a", offset++);
6858 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6860 aopPut (AOP (result), "a", offset++);
6868 aopPut (AOP (result), zero, offset++);
6874 /*-----------------------------------------------------------------*/
6875 /* genDataPointerGet - generates code when ptr offset is known */
6876 /*-----------------------------------------------------------------*/
6878 genDataPointerGet (operand * left,
6884 int size, offset = 0;
6885 aopOp (result, ic, TRUE);
6887 /* get the string representation of the name */
6888 l = aopGet (AOP (left), 0, FALSE, TRUE);
6889 size = AOP_SIZE (result);
6893 sprintf (buffer, "(%s + %d)", l + 1, offset);
6895 sprintf (buffer, "%s", l + 1);
6896 aopPut (AOP (result), buffer, offset++);
6899 freeAsmop (left, NULL, ic, TRUE);
6900 freeAsmop (result, NULL, ic, TRUE);
6903 /*-----------------------------------------------------------------*/
6904 /* genNearPointerGet - emitcode for near pointer fetch */
6905 /*-----------------------------------------------------------------*/
6907 genNearPointerGet (operand * left,
6915 sym_link *rtype, *retype;
6916 sym_link *ltype = operandType (left);
6919 rtype = operandType (result);
6920 retype = getSpec (rtype);
6922 aopOp (left, ic, FALSE);
6924 /* if left is rematerialisable and
6925 result is not bit variable type and
6926 the left is pointer to data space i.e
6927 lower 128 bytes of space */
6928 if (AOP_TYPE (left) == AOP_IMMD &&
6929 !IS_BITVAR (retype) &&
6930 DCL_TYPE (ltype) == POINTER)
6932 genDataPointerGet (left, result, ic);
6936 /* if the value is already in a pointer register
6937 then don't need anything more */
6938 if (!AOP_INPREG (AOP (left)))
6940 /* otherwise get a free pointer register */
6942 preg = getFreePtr (ic, &aop, FALSE);
6943 emitcode ("mov", "%s,%s",
6945 aopGet (AOP (left), 0, FALSE, TRUE));
6949 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6951 aopOp (result, ic, FALSE);
6953 /* if bitfield then unpack the bits */
6954 if (IS_BITVAR (retype))
6955 genUnpackBits (result, rname, POINTER);
6958 /* we have can just get the values */
6959 int size = AOP_SIZE (result);
6964 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6967 emitcode ("mov", "a,@%s", rname);
6968 aopPut (AOP (result), "a", offset);
6972 sprintf (buffer, "@%s", rname);
6973 aopPut (AOP (result), buffer, offset);
6977 emitcode ("inc", "%s", rname);
6981 /* now some housekeeping stuff */
6982 if (aop) /* we had to allocate for this iCode */
6984 if (pi) { /* post increment present */
6985 aopPut(AOP ( left ),rname,0);
6987 freeAsmop (NULL, aop, ic, TRUE);
6991 /* we did not allocate which means left
6992 already in a pointer register, then
6993 if size > 0 && this could be used again
6994 we have to point it back to where it
6996 if ((AOP_SIZE (result) > 1 &&
6997 !OP_SYMBOL (left)->remat &&
6998 (OP_SYMBOL (left)->liveTo > ic->seq ||
7002 int size = AOP_SIZE (result) - 1;
7004 emitcode ("dec", "%s", rname);
7009 freeAsmop (left, NULL, ic, TRUE);
7010 freeAsmop (result, NULL, ic, TRUE);
7011 if (pi) pi->generated = 1;
7014 /*-----------------------------------------------------------------*/
7015 /* genPagedPointerGet - emitcode for paged pointer fetch */
7016 /*-----------------------------------------------------------------*/
7018 genPagedPointerGet (operand * left,
7026 sym_link *rtype, *retype;
7028 rtype = operandType (result);
7029 retype = getSpec (rtype);
7031 aopOp (left, ic, FALSE);
7033 /* if the value is already in a pointer register
7034 then don't need anything more */
7035 if (!AOP_INPREG (AOP (left)))
7037 /* otherwise get a free pointer register */
7039 preg = getFreePtr (ic, &aop, FALSE);
7040 emitcode ("mov", "%s,%s",
7042 aopGet (AOP (left), 0, FALSE, TRUE));
7046 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7048 aopOp (result, ic, FALSE);
7050 /* if bitfield then unpack the bits */
7051 if (IS_BITVAR (retype))
7052 genUnpackBits (result, rname, PPOINTER);
7055 /* we have can just get the values */
7056 int size = AOP_SIZE (result);
7062 emitcode ("movx", "a,@%s", rname);
7063 aopPut (AOP (result), "a", offset);
7068 emitcode ("inc", "%s", rname);
7072 /* now some housekeeping stuff */
7073 if (aop) /* we had to allocate for this iCode */
7075 if (pi) aopPut ( AOP (left), rname, 0);
7076 freeAsmop (NULL, aop, ic, TRUE);
7080 /* we did not allocate which means left
7081 already in a pointer register, then
7082 if size > 0 && this could be used again
7083 we have to point it back to where it
7085 if ((AOP_SIZE (result) > 1 &&
7086 !OP_SYMBOL (left)->remat &&
7087 (OP_SYMBOL (left)->liveTo > ic->seq ||
7091 int size = AOP_SIZE (result) - 1;
7093 emitcode ("dec", "%s", rname);
7098 freeAsmop (left, NULL, ic, TRUE);
7099 freeAsmop (result, NULL, ic, TRUE);
7100 if (pi) pi->generated = 1;
7104 /*-----------------------------------------------------------------*/
7105 /* genFarPointerGet - gget value from far space */
7106 /*-----------------------------------------------------------------*/
7108 genFarPointerGet (operand * left,
7109 operand * result, iCode * ic, iCode * pi)
7112 sym_link *retype = getSpec (operandType (result));
7114 aopOp (left, ic, FALSE);
7116 /* if the operand is already in dptr
7117 then we do nothing else we move the value to dptr */
7118 if (AOP_TYPE (left) != AOP_STR)
7120 /* if this is remateriazable */
7121 if (AOP_TYPE (left) == AOP_IMMD)
7122 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7124 { /* we need to get it byte by byte */
7125 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7126 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7129 /* so dptr know contains the address */
7130 aopOp (result, ic, FALSE);
7132 /* if bit then unpack */
7133 if (IS_BITVAR (retype))
7134 genUnpackBits (result, "dptr", FPOINTER);
7137 size = AOP_SIZE (result);
7142 emitcode ("movx", "a,@dptr");
7143 aopPut (AOP (result), "a", offset++);
7145 emitcode ("inc", "dptr");
7149 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7150 aopPut ( AOP (left), "dpl", 0);
7151 aopPut ( AOP (left), "dph", 1);
7154 freeAsmop (left, NULL, ic, TRUE);
7155 freeAsmop (result, NULL, ic, TRUE);
7158 /*-----------------------------------------------------------------*/
7159 /* genCodePointerGet - gget value from code space */
7160 /*-----------------------------------------------------------------*/
7162 genCodePointerGet (operand * left,
7163 operand * result, iCode * ic, iCode *pi)
7166 sym_link *retype = getSpec (operandType (result));
7168 aopOp (left, ic, FALSE);
7170 /* if the operand is already in dptr
7171 then we do nothing else we move the value to dptr */
7172 if (AOP_TYPE (left) != AOP_STR)
7174 /* if this is remateriazable */
7175 if (AOP_TYPE (left) == AOP_IMMD)
7176 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7178 { /* we need to get it byte by byte */
7179 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7180 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7183 /* so dptr know contains the address */
7184 aopOp (result, ic, FALSE);
7186 /* if bit then unpack */
7187 if (IS_BITVAR (retype))
7188 genUnpackBits (result, "dptr", CPOINTER);
7191 size = AOP_SIZE (result);
7196 emitcode ("clr", "a");
7197 emitcode ("movc", "a,@a+dptr");
7198 aopPut (AOP (result), "a", offset++);
7200 emitcode ("inc", "dptr");
7204 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7205 aopPut ( AOP (left), "dpl", 0);
7206 aopPut ( AOP (left), "dph", 1);
7209 freeAsmop (left, NULL, ic, TRUE);
7210 freeAsmop (result, NULL, ic, TRUE);
7213 /*-----------------------------------------------------------------*/
7214 /* genGenPointerGet - gget value from generic pointer space */
7215 /*-----------------------------------------------------------------*/
7217 genGenPointerGet (operand * left,
7218 operand * result, iCode * ic, iCode *pi)
7221 sym_link *retype = getSpec (operandType (result));
7223 aopOp (left, ic, FALSE);
7225 /* if the operand is already in dptr
7226 then we do nothing else we move the value to dptr */
7227 if (AOP_TYPE (left) != AOP_STR)
7229 /* if this is remateriazable */
7230 if (AOP_TYPE (left) == AOP_IMMD)
7232 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7233 emitcode ("mov", "b,#%d", pointerCode (retype));
7236 { /* we need to get it byte by byte */
7237 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7238 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7239 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7242 /* so dptr know contains the address */
7243 aopOp (result, ic, FALSE);
7245 /* if bit then unpack */
7246 if (IS_BITVAR (retype))
7247 genUnpackBits (result, "dptr", GPOINTER);
7250 size = AOP_SIZE (result);
7255 emitcode ("lcall", "__gptrget");
7256 aopPut (AOP (result), "a", offset++);
7258 emitcode ("inc", "dptr");
7262 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7263 aopPut ( AOP (left), "dpl", 0);
7264 aopPut ( AOP (left), "dph", 1);
7267 freeAsmop (left, NULL, ic, TRUE);
7268 freeAsmop (result, NULL, ic, TRUE);
7271 /*-----------------------------------------------------------------*/
7272 /* genPointerGet - generate code for pointer get */
7273 /*-----------------------------------------------------------------*/
7275 genPointerGet (iCode * ic, iCode *pi)
7277 operand *left, *result;
7278 sym_link *type, *etype;
7281 left = IC_LEFT (ic);
7282 result = IC_RESULT (ic);
7284 /* depending on the type of pointer we need to
7285 move it to the correct pointer register */
7286 type = operandType (left);
7287 etype = getSpec (type);
7288 /* if left is of type of pointer then it is simple */
7289 if (IS_PTR (type) && !IS_FUNC (type->next))
7290 p_type = DCL_TYPE (type);
7293 /* we have to go by the storage class */
7294 p_type = PTR_TYPE (SPEC_OCLS (etype));
7297 /* now that we have the pointer type we assign
7298 the pointer values */
7304 genNearPointerGet (left, result, ic, pi);
7308 genPagedPointerGet (left, result, ic, pi);
7312 genFarPointerGet (left, result, ic, pi);
7316 genCodePointerGet (left, result, ic, pi);
7320 genGenPointerGet (left, result, ic, pi);
7326 /*-----------------------------------------------------------------*/
7327 /* genPackBits - generates code for packed bit storage */
7328 /*-----------------------------------------------------------------*/
7330 genPackBits (sym_link * etype,
7332 char *rname, int p_type)
7340 blen = SPEC_BLEN (etype);
7341 bstr = SPEC_BSTR (etype);
7343 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7346 /* if the bit lenth is less than or */
7347 /* it exactly fits a byte then */
7348 if (SPEC_BLEN (etype) <= 8)
7350 shCount = SPEC_BSTR (etype);
7352 /* shift left acc */
7355 if (SPEC_BLEN (etype) < 8)
7356 { /* if smaller than a byte */
7362 emitcode ("mov", "b,a");
7363 emitcode ("mov", "a,@%s", rname);
7367 emitcode ("mov", "b,a");
7368 emitcode ("movx", "a,@dptr");
7372 emitcode ("push", "b");
7373 emitcode ("push", "acc");
7374 emitcode ("lcall", "__gptrget");
7375 emitcode ("pop", "b");
7379 emitcode ("anl", "a,#0x%02x", (unsigned char)
7380 ((unsigned char) (0xFF << (blen + bstr)) |
7381 (unsigned char) (0xFF >> (8 - bstr))));
7382 emitcode ("orl", "a,b");
7383 if (p_type == GPOINTER)
7384 emitcode ("pop", "b");
7391 emitcode ("mov", "@%s,a", rname);
7395 emitcode ("movx", "@dptr,a");
7399 emitcode ("lcall", "__gptrput");
7404 if (SPEC_BLEN (etype) <= 8)
7407 emitcode ("inc", "%s", rname);
7408 rLen = SPEC_BLEN (etype);
7410 /* now generate for lengths greater than one byte */
7414 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7426 emitcode ("mov", "@%s,a", rname);
7429 emitcode ("mov", "@%s,%s", rname, l);
7434 emitcode ("movx", "@dptr,a");
7439 emitcode ("lcall", "__gptrput");
7442 emitcode ("inc", "%s", rname);
7447 /* last last was not complete */
7450 /* save the byte & read byte */
7454 emitcode ("mov", "b,a");
7455 emitcode ("mov", "a,@%s", rname);
7459 emitcode ("mov", "b,a");
7460 emitcode ("movx", "a,@dptr");
7464 emitcode ("push", "b");
7465 emitcode ("push", "acc");
7466 emitcode ("lcall", "__gptrget");
7467 emitcode ("pop", "b");
7471 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7472 emitcode ("orl", "a,b");
7475 if (p_type == GPOINTER)
7476 emitcode ("pop", "b");
7482 emitcode ("mov", "@%s,a", rname);
7486 emitcode ("movx", "@dptr,a");
7490 emitcode ("lcall", "__gptrput");
7494 /*-----------------------------------------------------------------*/
7495 /* genDataPointerSet - remat pointer to data space */
7496 /*-----------------------------------------------------------------*/
7498 genDataPointerSet (operand * right,
7502 int size, offset = 0;
7503 char *l, buffer[256];
7505 aopOp (right, ic, FALSE);
7507 l = aopGet (AOP (result), 0, FALSE, TRUE);
7508 size = AOP_SIZE (right);
7512 sprintf (buffer, "(%s + %d)", l + 1, offset);
7514 sprintf (buffer, "%s", l + 1);
7515 emitcode ("mov", "%s,%s", buffer,
7516 aopGet (AOP (right), offset++, FALSE, FALSE));
7519 freeAsmop (right, NULL, ic, TRUE);
7520 freeAsmop (result, NULL, ic, TRUE);
7523 /*-----------------------------------------------------------------*/
7524 /* genNearPointerSet - emitcode for near pointer put */
7525 /*-----------------------------------------------------------------*/
7527 genNearPointerSet (operand * right,
7535 sym_link *retype, *letype;
7536 sym_link *ptype = operandType (result);
7538 retype = getSpec (operandType (right));
7539 letype = getSpec (ptype);
7540 aopOp (result, ic, FALSE);
7542 /* if the result is rematerializable &
7543 in data space & not a bit variable */
7544 if (AOP_TYPE (result) == AOP_IMMD &&
7545 DCL_TYPE (ptype) == POINTER &&
7546 !IS_BITVAR (retype) &&
7547 !IS_BITVAR (letype))
7549 genDataPointerSet (right, result, ic);
7553 /* if the value is already in a pointer register
7554 then don't need anything more */
7555 if (!AOP_INPREG (AOP (result)))
7557 /* otherwise get a free pointer register */
7559 preg = getFreePtr (ic, &aop, FALSE);
7560 emitcode ("mov", "%s,%s",
7562 aopGet (AOP (result), 0, FALSE, TRUE));
7566 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7568 aopOp (right, ic, FALSE);
7570 /* if bitfield then unpack the bits */
7571 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7572 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7575 /* we have can just get the values */
7576 int size = AOP_SIZE (right);
7581 l = aopGet (AOP (right), offset, FALSE, TRUE);
7585 emitcode ("mov", "@%s,a", rname);
7588 emitcode ("mov", "@%s,%s", rname, l);
7590 emitcode ("inc", "%s", rname);
7595 /* now some housekeeping stuff */
7596 if (aop) /* we had to allocate for this iCode */
7598 if (pi) aopPut (AOP (result),rname,0);
7599 freeAsmop (NULL, aop, ic, TRUE);
7603 /* we did not allocate which means left
7604 already in a pointer register, then
7605 if size > 0 && this could be used again
7606 we have to point it back to where it
7608 if ((AOP_SIZE (right) > 1 &&
7609 !OP_SYMBOL (result)->remat &&
7610 (OP_SYMBOL (result)->liveTo > ic->seq ||
7614 int size = AOP_SIZE (right) - 1;
7616 emitcode ("dec", "%s", rname);
7621 if (pi) pi->generated = 1;
7622 freeAsmop (result, NULL, ic, TRUE);
7623 freeAsmop (right, NULL, ic, TRUE);
7626 /*-----------------------------------------------------------------*/
7627 /* genPagedPointerSet - emitcode for Paged pointer put */
7628 /*-----------------------------------------------------------------*/
7630 genPagedPointerSet (operand * right,
7638 sym_link *retype, *letype;
7640 retype = getSpec (operandType (right));
7641 letype = getSpec (operandType (result));
7643 aopOp (result, ic, FALSE);
7645 /* if the value is already in a pointer register
7646 then don't need anything more */
7647 if (!AOP_INPREG (AOP (result)))
7649 /* otherwise get a free pointer register */
7651 preg = getFreePtr (ic, &aop, FALSE);
7652 emitcode ("mov", "%s,%s",
7654 aopGet (AOP (result), 0, FALSE, TRUE));
7658 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7660 aopOp (right, ic, FALSE);
7662 /* if bitfield then unpack the bits */
7663 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7664 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7667 /* we have can just get the values */
7668 int size = AOP_SIZE (right);
7673 l = aopGet (AOP (right), offset, FALSE, TRUE);
7676 emitcode ("movx", "@%s,a", rname);
7679 emitcode ("inc", "%s", rname);
7685 /* now some housekeeping stuff */
7686 if (aop) /* we had to allocate for this iCode */
7688 if (pi) aopPut (AOP (result),rname,0);
7689 freeAsmop (NULL, aop, ic, TRUE);
7693 /* we did not allocate which means left
7694 already in a pointer register, then
7695 if size > 0 && this could be used again
7696 we have to point it back to where it
7698 if (AOP_SIZE (right) > 1 &&
7699 !OP_SYMBOL (result)->remat &&
7700 (OP_SYMBOL (result)->liveTo > ic->seq ||
7703 int size = AOP_SIZE (right) - 1;
7705 emitcode ("dec", "%s", rname);
7710 if (pi) pi->generated = 1;
7711 freeAsmop (result, NULL, ic, TRUE);
7712 freeAsmop (right, NULL, ic, TRUE);
7717 /*-----------------------------------------------------------------*/
7718 /* genFarPointerSet - set value from far space */
7719 /*-----------------------------------------------------------------*/
7721 genFarPointerSet (operand * right,
7722 operand * result, iCode * ic, iCode * pi)
7725 sym_link *retype = getSpec (operandType (right));
7726 sym_link *letype = getSpec (operandType (result));
7727 aopOp (result, ic, FALSE);
7729 /* if the operand is already in dptr
7730 then we do nothing else we move the value to dptr */
7731 if (AOP_TYPE (result) != AOP_STR)
7733 /* if this is remateriazable */
7734 if (AOP_TYPE (result) == AOP_IMMD)
7735 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7737 { /* we need to get it byte by byte */
7738 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7739 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7742 /* so dptr know contains the address */
7743 aopOp (right, ic, FALSE);
7745 /* if bit then unpack */
7746 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7747 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7750 size = AOP_SIZE (right);
7755 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7757 emitcode ("movx", "@dptr,a");
7759 emitcode ("inc", "dptr");
7762 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7763 aopPut (AOP(result),"dpl",0);
7764 aopPut (AOP(result),"dph",1);
7767 freeAsmop (result, NULL, ic, TRUE);
7768 freeAsmop (right, NULL, ic, TRUE);
7771 /*-----------------------------------------------------------------*/
7772 /* genGenPointerSet - set value from generic pointer space */
7773 /*-----------------------------------------------------------------*/
7775 genGenPointerSet (operand * right,
7776 operand * result, iCode * ic, iCode * pi)
7779 sym_link *retype = getSpec (operandType (right));
7780 sym_link *letype = getSpec (operandType (result));
7782 aopOp (result, ic, FALSE);
7784 /* if the operand is already in dptr
7785 then we do nothing else we move the value to dptr */
7786 if (AOP_TYPE (result) != AOP_STR)
7788 /* if this is remateriazable */
7789 if (AOP_TYPE (result) == AOP_IMMD)
7791 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7792 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7795 { /* we need to get it byte by byte */
7796 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7797 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7798 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7801 /* so dptr know contains the address */
7802 aopOp (right, ic, FALSE);
7804 /* if bit then unpack */
7805 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7806 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7809 size = AOP_SIZE (right);
7814 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7816 emitcode ("lcall", "__gptrput");
7818 emitcode ("inc", "dptr");
7822 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7823 aopPut (AOP(result),"dpl",0);
7824 aopPut (AOP(result),"dph",1);
7827 freeAsmop (result, NULL, ic, TRUE);
7828 freeAsmop (right, NULL, ic, TRUE);
7831 /*-----------------------------------------------------------------*/
7832 /* genPointerSet - stores the value into a pointer location */
7833 /*-----------------------------------------------------------------*/
7835 genPointerSet (iCode * ic, iCode *pi)
7837 operand *right, *result;
7838 sym_link *type, *etype;
7841 right = IC_RIGHT (ic);
7842 result = IC_RESULT (ic);
7844 /* depending on the type of pointer we need to
7845 move it to the correct pointer register */
7846 type = operandType (result);
7847 etype = getSpec (type);
7848 /* if left is of type of pointer then it is simple */
7849 if (IS_PTR (type) && !IS_FUNC (type->next))
7851 p_type = DCL_TYPE (type);
7855 /* we have to go by the storage class */
7856 p_type = PTR_TYPE (SPEC_OCLS (etype));
7859 /* now that we have the pointer type we assign
7860 the pointer values */
7866 genNearPointerSet (right, result, ic, pi);
7870 genPagedPointerSet (right, result, ic, pi);
7874 genFarPointerSet (right, result, ic, pi);
7878 genGenPointerSet (right, result, ic, pi);
7884 /*-----------------------------------------------------------------*/
7885 /* genIfx - generate code for Ifx statement */
7886 /*-----------------------------------------------------------------*/
7888 genIfx (iCode * ic, iCode * popIc)
7890 operand *cond = IC_COND (ic);
7893 aopOp (cond, ic, FALSE);
7895 /* get the value into acc */
7896 if (AOP_TYPE (cond) != AOP_CRY)
7900 /* the result is now in the accumulator */
7901 freeAsmop (cond, NULL, ic, TRUE);
7903 /* if there was something to be popped then do it */
7907 /* if the condition is a bit variable */
7908 if (isbit && IS_ITEMP (cond) &&
7910 genIfxJump (ic, SPIL_LOC (cond)->rname);
7911 else if (isbit && !IS_ITEMP (cond))
7912 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7914 genIfxJump (ic, "a");
7919 /*-----------------------------------------------------------------*/
7920 /* genAddrOf - generates code for address of */
7921 /*-----------------------------------------------------------------*/
7923 genAddrOf (iCode * ic)
7925 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7928 aopOp (IC_RESULT (ic), ic, FALSE);
7930 /* if the operand is on the stack then we
7931 need to get the stack offset of this
7935 /* if it has an offset then we need to compute
7939 emitcode ("mov", "a,_bp");
7940 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7941 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7945 /* we can just move _bp */
7946 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7948 /* fill the result with zero */
7949 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7954 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7960 /* object not on stack then we need the name */
7961 size = AOP_SIZE (IC_RESULT (ic));
7966 char s[SDCC_NAME_MAX];
7968 sprintf (s, "#(%s >> %d)",
7972 sprintf (s, "#%s", sym->rname);
7973 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7977 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7981 /*-----------------------------------------------------------------*/
7982 /* genFarFarAssign - assignment when both are in far space */
7983 /*-----------------------------------------------------------------*/
7985 genFarFarAssign (operand * result, operand * right, iCode * ic)
7987 int size = AOP_SIZE (right);
7990 /* first push the right side on to the stack */
7993 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7995 emitcode ("push", "acc");
7998 freeAsmop (right, NULL, ic, FALSE);
7999 /* now assign DPTR to result */
8000 aopOp (result, ic, FALSE);
8001 size = AOP_SIZE (result);
8004 emitcode ("pop", "acc");
8005 aopPut (AOP (result), "a", --offset);
8007 freeAsmop (result, NULL, ic, FALSE);
8011 /*-----------------------------------------------------------------*/
8012 /* genAssign - generate code for assignment */
8013 /*-----------------------------------------------------------------*/
8015 genAssign (iCode * ic)
8017 operand *result, *right;
8019 unsigned long lit = 0L;
8021 D(emitcode(";","genAssign"));
8023 result = IC_RESULT (ic);
8024 right = IC_RIGHT (ic);
8026 /* if they are the same */
8027 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8030 aopOp (right, ic, FALSE);
8032 /* special case both in far space */
8033 if (AOP_TYPE (right) == AOP_DPTR &&
8034 IS_TRUE_SYMOP (result) &&
8035 isOperandInFarSpace (result))
8038 genFarFarAssign (result, right, ic);
8042 aopOp (result, ic, TRUE);
8044 /* if they are the same registers */
8045 if (sameRegs (AOP (right), AOP (result)))
8048 /* if the result is a bit */
8049 if (AOP_TYPE (result) == AOP_CRY)
8052 /* if the right size is a literal then
8053 we know what the value is */
8054 if (AOP_TYPE (right) == AOP_LIT)
8056 if (((int) operandLitValue (right)))
8057 aopPut (AOP (result), one, 0);
8059 aopPut (AOP (result), zero, 0);
8063 /* the right is also a bit variable */
8064 if (AOP_TYPE (right) == AOP_CRY)
8066 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8067 aopPut (AOP (result), "c", 0);
8073 aopPut (AOP (result), "a", 0);
8077 /* bit variables done */
8079 size = AOP_SIZE (result);
8081 if (AOP_TYPE (right) == AOP_LIT)
8082 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8084 (AOP_TYPE (result) != AOP_REG) &&
8085 (AOP_TYPE (right) == AOP_LIT) &&
8086 !IS_FLOAT (operandType (right)) &&
8089 emitcode ("clr", "a");
8092 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8093 aopPut (AOP (result), "a", size);
8095 aopPut (AOP (result),
8096 aopGet (AOP (right), size, FALSE, FALSE),
8104 aopPut (AOP (result),
8105 aopGet (AOP (right), offset, FALSE, FALSE),
8112 freeAsmop (right, NULL, ic, TRUE);
8113 freeAsmop (result, NULL, ic, TRUE);
8116 /*-----------------------------------------------------------------*/
8117 /* genJumpTab - genrates code for jump table */
8118 /*-----------------------------------------------------------------*/
8120 genJumpTab (iCode * ic)
8125 aopOp (IC_JTCOND (ic), ic, FALSE);
8126 /* get the condition into accumulator */
8127 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8129 /* multiply by three */
8130 emitcode ("add", "a,acc");
8131 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8132 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8134 jtab = newiTempLabel (NULL);
8135 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8136 emitcode ("jmp", "@a+dptr");
8137 emitcode ("", "%05d$:", jtab->key + 100);
8138 /* now generate the jump labels */
8139 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8140 jtab = setNextItem (IC_JTLABELS (ic)))
8141 emitcode ("ljmp", "%05d$", jtab->key + 100);
8145 /*-----------------------------------------------------------------*/
8146 /* genCast - gen code for casting */
8147 /*-----------------------------------------------------------------*/
8149 genCast (iCode * ic)
8151 operand *result = IC_RESULT (ic);
8152 sym_link *ctype = operandType (IC_LEFT (ic));
8153 sym_link *rtype = operandType (IC_RIGHT (ic));
8154 operand *right = IC_RIGHT (ic);
8157 D(emitcode(";", "genCast"));
8159 /* if they are equivalent then do nothing */
8160 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8163 aopOp (right, ic, FALSE);
8164 aopOp (result, ic, FALSE);
8166 /* if the result is a bit */
8167 if (AOP_TYPE (result) == AOP_CRY)
8169 /* if the right size is a literal then
8170 we know what the value is */
8171 if (AOP_TYPE (right) == AOP_LIT)
8173 if (((int) operandLitValue (right)))
8174 aopPut (AOP (result), one, 0);
8176 aopPut (AOP (result), zero, 0);
8181 /* the right is also a bit variable */
8182 if (AOP_TYPE (right) == AOP_CRY)
8184 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8185 aopPut (AOP (result), "c", 0);
8191 aopPut (AOP (result), "a", 0);
8195 /* if they are the same size : or less */
8196 if (AOP_SIZE (result) <= AOP_SIZE (right))
8199 /* if they are in the same place */
8200 if (sameRegs (AOP (right), AOP (result)))
8203 /* if they in different places then copy */
8204 size = AOP_SIZE (result);
8208 aopPut (AOP (result),
8209 aopGet (AOP (right), offset, FALSE, FALSE),
8217 /* if the result is of type pointer */
8222 sym_link *type = operandType (right);
8223 sym_link *etype = getSpec (type);
8225 /* pointer to generic pointer */
8226 if (IS_GENPTR (ctype))
8231 p_type = DCL_TYPE (type);
8234 if (SPEC_SCLS(etype)==S_REGISTER) {
8235 // let's assume it is a generic pointer
8238 /* we have to go by the storage class */
8239 p_type = PTR_TYPE (SPEC_OCLS (etype));
8243 /* the first two bytes are known */
8244 size = GPTRSIZE - 1;
8248 aopPut (AOP (result),
8249 aopGet (AOP (right), offset, FALSE, FALSE),
8253 /* the last byte depending on type */
8269 case PPOINTER: // what the fck is this?
8274 /* this should never happen */
8275 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8276 "got unknown pointer type");
8279 aopPut (AOP (result), l, GPTRSIZE - 1);
8283 /* just copy the pointers */
8284 size = AOP_SIZE (result);
8288 aopPut (AOP (result),
8289 aopGet (AOP (right), offset, FALSE, FALSE),
8296 /* so we now know that the size of destination is greater
8297 than the size of the source */
8298 /* we move to result for the size of source */
8299 size = AOP_SIZE (right);
8303 aopPut (AOP (result),
8304 aopGet (AOP (right), offset, FALSE, FALSE),
8309 /* now depending on the sign of the source && destination */
8310 size = AOP_SIZE (result) - AOP_SIZE (right);
8311 /* if unsigned or not an integral type */
8312 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8315 aopPut (AOP (result), zero, offset++);
8319 /* we need to extend the sign :{ */
8320 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8323 emitcode ("rlc", "a");
8324 emitcode ("subb", "a,acc");
8326 aopPut (AOP (result), "a", offset++);
8329 /* we are done hurray !!!! */
8332 freeAsmop (right, NULL, ic, TRUE);
8333 freeAsmop (result, NULL, ic, TRUE);
8337 /*-----------------------------------------------------------------*/
8338 /* genDjnz - generate decrement & jump if not zero instrucion */
8339 /*-----------------------------------------------------------------*/
8341 genDjnz (iCode * ic, iCode * ifx)
8347 /* if the if condition has a false label
8348 then we cannot save */
8352 /* if the minus is not of the form
8354 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8355 !IS_OP_LITERAL (IC_RIGHT (ic)))
8358 if (operandLitValue (IC_RIGHT (ic)) != 1)
8361 /* if the size of this greater than one then no
8363 if (getSize (operandType (IC_RESULT (ic))) > 1)
8366 /* otherwise we can save BIG */
8367 lbl = newiTempLabel (NULL);
8368 lbl1 = newiTempLabel (NULL);
8370 aopOp (IC_RESULT (ic), ic, FALSE);
8372 if (AOP_NEEDSACC(IC_RESULT(ic)))
8374 /* If the result is accessed indirectly via
8375 * the accumulator, we must explicitly write
8376 * it back after the decrement.
8378 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8380 if (strcmp(rByte, "a"))
8382 /* Something is hopelessly wrong */
8383 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8384 __FILE__, __LINE__);
8385 /* We can just give up; the generated code will be inefficient,
8388 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8391 emitcode ("dec", "%s", rByte);
8392 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8393 emitcode ("jnz", "%05d$", lbl->key + 100);
8395 else if (IS_AOP_PREG (IC_RESULT (ic)))
8397 emitcode ("dec", "%s",
8398 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8399 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8400 emitcode ("jnz", "%05d$", lbl->key + 100);
8404 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8407 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8408 emitcode ("", "%05d$:", lbl->key + 100);
8409 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8410 emitcode ("", "%05d$:", lbl1->key + 100);
8412 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8417 /*-----------------------------------------------------------------*/
8418 /* genReceive - generate code for a receive iCode */
8419 /*-----------------------------------------------------------------*/
8421 genReceive (iCode * ic)
8423 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8424 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8425 IS_TRUE_SYMOP (IC_RESULT (ic))))
8428 int size = getSize (operandType (IC_RESULT (ic)));
8429 int offset = fReturnSizeMCS51 - size;
8432 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8433 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8436 aopOp (IC_RESULT (ic), ic, FALSE);
8437 size = AOP_SIZE (IC_RESULT (ic));
8441 emitcode ("pop", "acc");
8442 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8449 aopOp (IC_RESULT (ic), ic, FALSE);
8451 assignResultValue (IC_RESULT (ic));
8454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8457 /*-----------------------------------------------------------------*/
8458 /* gen51Code - generate code for 8051 based controllers */
8459 /*-----------------------------------------------------------------*/
8461 gen51Code (iCode * lic)
8466 lineHead = lineCurr = NULL;
8468 /* print the allocation information */
8470 printAllocInfo (currFunc, codeOutFile);
8471 /* if debug information required */
8472 /* if (options.debug && currFunc) { */
8473 if (options.debug && currFunc)
8475 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8477 if (IS_STATIC (currFunc->etype))
8478 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8480 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8483 /* stack pointer name */
8484 if (options.useXstack)
8490 for (ic = lic; ic; ic = ic->next)
8493 if (cln != ic->lineno)
8498 emitcode ("", "C$%s$%d$%d$%d ==.",
8499 FileBaseName (ic->filename), ic->lineno,
8500 ic->level, ic->block);
8503 emitcode (";", "%s %d", ic->filename, ic->lineno);
8506 /* if the result is marked as
8507 spilt and rematerializable or code for
8508 this has already been generated then
8510 if (resultRemat (ic) || ic->generated)
8513 /* depending on the operation */
8533 /* IPOP happens only when trying to restore a
8534 spilt live range, if there is an ifx statement
8535 following this pop then the if statement might
8536 be using some of the registers being popped which
8537 would destory the contents of the register so
8538 we need to check for this condition and handle it */
8540 ic->next->op == IFX &&
8541 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8542 genIfx (ic->next, ic);
8560 genEndFunction (ic);
8580 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8597 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8601 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8608 /* note these two are xlated by algebraic equivalence
8609 during parsing SDCC.y */
8610 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8611 "got '>=' or '<=' shouldn't have come here");
8615 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8627 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8631 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8635 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8662 case GET_VALUE_AT_ADDRESS:
8663 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8667 if (POINTER_SET (ic))
8668 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8694 addSet (&_G.sendSet, ic);
8703 /* now we are ready to call the
8704 peep hole optimizer */
8705 if (!options.nopeep)
8706 peepHole (&lineHead);
8708 /* now do the actual printing */
8709 printLine (lineHead, codeOutFile);