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>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
385 val += (int) operandLitValue (IC_RIGHT (ic));
386 else if (ic->op == '-')
387 val -= (int) operandLitValue (IC_RIGHT (ic));
391 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
395 sprintf (buffer, "(%s %c 0x%04x)",
396 OP_SYMBOL (IC_LEFT (ic))->rname,
397 val >= 0 ? '+' : '-',
400 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
402 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
403 strcpy (aop->aopu.aop_immd, buffer);
407 /*-----------------------------------------------------------------*/
408 /* regsInCommon - two operands have some registers in common */
409 /*-----------------------------------------------------------------*/
411 regsInCommon (operand * op1, operand * op2)
416 /* if they have registers in common */
417 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
420 sym1 = OP_SYMBOL (op1);
421 sym2 = OP_SYMBOL (op2);
423 if (sym1->nRegs == 0 || sym2->nRegs == 0)
426 for (i = 0; i < sym1->nRegs; i++)
432 for (j = 0; j < sym2->nRegs; j++)
437 if (sym2->regs[j] == sym1->regs[i])
445 /*-----------------------------------------------------------------*/
446 /* operandsEqu - equivalent */
447 /*-----------------------------------------------------------------*/
449 operandsEqu (operand * op1, operand * op2)
453 /* if they not symbols */
454 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
457 sym1 = OP_SYMBOL (op1);
458 sym2 = OP_SYMBOL (op2);
460 /* if both are itemps & one is spilt
461 and the other is not then false */
462 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
463 sym1->isspilt != sym2->isspilt)
466 /* if they are the same */
470 if (strcmp (sym1->rname, sym2->rname) == 0)
474 /* if left is a tmp & right is not */
475 if (IS_ITEMP (op1) &&
478 (sym1->usl.spillLoc == sym2))
481 if (IS_ITEMP (op2) &&
485 (sym2->usl.spillLoc == sym1))
491 /*-----------------------------------------------------------------*/
492 /* sameRegs - two asmops have the same registers */
493 /*-----------------------------------------------------------------*/
495 sameRegs (asmop * aop1, asmop * aop2)
502 if (aop1->type != AOP_REG ||
503 aop2->type != AOP_REG)
506 if (aop1->size != aop2->size)
509 for (i = 0; i < aop1->size; i++)
510 if (aop1->aopu.aop_reg[i] !=
511 aop2->aopu.aop_reg[i])
517 /*-----------------------------------------------------------------*/
518 /* aopOp - allocates an asmop for an operand : */
519 /*-----------------------------------------------------------------*/
521 aopOp (operand * op, iCode * ic, bool result)
530 /* if this a literal */
531 if (IS_OP_LITERAL (op))
533 op->aop = aop = newAsmop (AOP_LIT);
534 aop->aopu.aop_lit = op->operand.valOperand;
535 aop->size = getSize (operandType (op));
539 /* if already has a asmop then continue */
543 /* if the underlying symbol has a aop */
544 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
546 op->aop = OP_SYMBOL (op)->aop;
550 /* if this is a true symbol */
551 if (IS_TRUE_SYMOP (op))
553 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
557 /* this is a temporary : this has
563 e) can be a return use only */
565 sym = OP_SYMBOL (op);
567 /* if the type is a conditional */
568 if (sym->regType == REG_CND)
570 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
575 /* if it is spilt then two situations
577 b) has a spill location */
578 if (sym->isspilt || sym->nRegs == 0)
581 /* rematerialize it NOW */
584 sym->aop = op->aop = aop =
586 aop->size = getSize (sym->type);
593 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
594 aop->size = getSize (sym->type);
595 for (i = 0; i < 2; i++)
596 aop->aopu.aop_str[i] = accUse[i];
604 aop = op->aop = sym->aop = newAsmop (AOP_STR);
605 aop->size = getSize (sym->type);
606 for (i = 0; i < fReturnSizeMCS51; i++)
607 aop->aopu.aop_str[i] = fReturn[i];
611 /* else spill location */
612 sym->aop = op->aop = aop =
613 aopForSym (ic, sym->usl.spillLoc, result);
614 aop->size = getSize (sym->type);
618 /* must be in a register */
619 sym->aop = op->aop = aop = newAsmop (AOP_REG);
620 aop->size = sym->nRegs;
621 for (i = 0; i < sym->nRegs; i++)
622 aop->aopu.aop_reg[i] = sym->regs[i];
625 /*-----------------------------------------------------------------*/
626 /* freeAsmop - free up the asmop given to an operand */
627 /*----------------------------------------------------------------*/
629 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
646 /* depending on the asmop type only three cases need work AOP_RO
647 , AOP_R1 && AOP_STK */
655 emitcode ("pop", "ar0");
659 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 emitcode ("pop", "ar1");
671 bitVectUnSetBit (ic->rUsed, R1_IDX);
677 int stk = aop->aopu.aop_stk + aop->size;
678 bitVectUnSetBit (ic->rUsed, R0_IDX);
679 bitVectUnSetBit (ic->rUsed, R1_IDX);
681 getFreePtr (ic, &aop, FALSE);
685 emitcode ("mov", "a,_bp");
686 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
687 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
691 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
696 emitcode ("pop", "acc");
697 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
700 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
703 freeAsmop (op, NULL, ic, TRUE);
706 emitcode ("pop", "ar0");
712 emitcode ("pop", "ar1");
719 /* all other cases just dealloc */
725 OP_SYMBOL (op)->aop = NULL;
726 /* if the symbol has a spill */
728 SPIL_LOC (op)->aop = NULL;
733 /*-----------------------------------------------------------------*/
734 /* aopGet - for fetching value of the aop */
735 /*-----------------------------------------------------------------*/
737 aopGet (asmop * aop, int offset, bool bit16, bool dname)
742 /* offset is greater than
744 if (offset > (aop->size - 1) &&
745 aop->type != AOP_LIT)
748 /* depending on type */
754 /* if we need to increment it */
755 while (offset > aop->coff)
757 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
761 while (offset < aop->coff)
763 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
770 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
771 return (dname ? "acc" : "a");
773 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
774 rs = Safe_calloc (1, strlen (s) + 1);
779 while (offset > aop->coff)
781 emitcode ("inc", "dptr");
785 while (offset < aop->coff)
787 emitcode ("lcall", "__decdptr");
794 emitcode ("clr", "a");
795 emitcode ("movc", "a,@a+dptr");
799 emitcode ("movx", "a,@dptr");
801 return (dname ? "acc" : "a");
806 sprintf (s, "#%s", aop->aopu.aop_immd);
808 sprintf (s, "#(%s >> %d)",
814 rs = Safe_calloc (1, strlen (s) + 1);
820 sprintf (s, "(%s + %d)",
824 sprintf (s, "%s", aop->aopu.aop_dir);
825 rs = Safe_calloc (1, strlen (s) + 1);
831 return aop->aopu.aop_reg[offset]->dname;
833 return aop->aopu.aop_reg[offset]->name;
836 emitcode ("clr", "a");
837 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
838 emitcode ("rlc", "a");
839 return (dname ? "acc" : "a");
842 if (!offset && dname)
844 return aop->aopu.aop_str[offset];
847 return aopLiteral (aop->aopu.aop_lit, offset);
851 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
855 return aop->aopu.aop_str[offset];
859 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
860 "aopget got unsupported aop->type");
863 /*-----------------------------------------------------------------*/
864 /* aopPut - puts a string for a aop */
865 /*-----------------------------------------------------------------*/
867 aopPut (asmop * aop, char *s, int offset)
871 if (aop->size && offset > (aop->size - 1))
873 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
874 "aopPut got offset > aop->size");
878 /* will assign value to value */
879 /* depending on where it is ofcourse */
884 sprintf (d, "(%s + %d)",
885 aop->aopu.aop_dir, offset);
887 sprintf (d, "%s", aop->aopu.aop_dir);
890 emitcode ("mov", "%s,%s", d, s);
895 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
896 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
899 strcmp (s, "r0") == 0 ||
900 strcmp (s, "r1") == 0 ||
901 strcmp (s, "r2") == 0 ||
902 strcmp (s, "r3") == 0 ||
903 strcmp (s, "r4") == 0 ||
904 strcmp (s, "r5") == 0 ||
905 strcmp (s, "r6") == 0 ||
906 strcmp (s, "r7") == 0)
907 emitcode ("mov", "%s,%s",
908 aop->aopu.aop_reg[offset]->dname, s);
910 emitcode ("mov", "%s,%s",
911 aop->aopu.aop_reg[offset]->name, s);
918 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
919 "aopPut writting to code space");
923 while (offset > aop->coff)
926 emitcode ("inc", "dptr");
929 while (offset < aop->coff)
932 emitcode ("lcall", "__decdptr");
937 /* if not in accumulater */
940 emitcode ("movx", "@dptr,a");
945 while (offset > aop->coff)
948 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
950 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
966 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
968 else if (strcmp (s, "r0") == 0 ||
969 strcmp (s, "r1") == 0 ||
970 strcmp (s, "r2") == 0 ||
971 strcmp (s, "r3") == 0 ||
972 strcmp (s, "r4") == 0 ||
973 strcmp (s, "r5") == 0 ||
974 strcmp (s, "r6") == 0 ||
975 strcmp (s, "r7") == 0)
978 sprintf (buffer, "a%s", s);
979 emitcode ("mov", "@%s,%s",
980 aop->aopu.aop_ptr->name, buffer);
983 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
988 if (strcmp (s, "a") == 0)
989 emitcode ("push", "acc");
991 emitcode ("push", "%s", s);
996 /* if bit variable */
997 if (!aop->aopu.aop_dir)
999 emitcode ("clr", "a");
1000 emitcode ("rlc", "a");
1005 emitcode ("clr", "%s", aop->aopu.aop_dir);
1007 emitcode ("setb", "%s", aop->aopu.aop_dir);
1008 else if (!strcmp (s, "c"))
1009 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1012 if (strcmp (s, "a"))
1017 symbol *lbl = newiTempLabel (NULL);
1018 emitcode ("clr", "c");
1019 emitcode ("jz", "%05d$", lbl->key + 100);
1020 emitcode ("cpl", "c");
1021 emitcode ("", "%05d$:", lbl->key + 100);
1022 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1030 if (strcmp (aop->aopu.aop_str[offset], s))
1031 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1036 if (!offset && (strcmp (s, "acc") == 0))
1039 if (strcmp (aop->aopu.aop_str[offset], s))
1040 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1044 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1045 "aopPut got unsupported aop->type");
1053 /*-----------------------------------------------------------------*/
1054 /* pointToEnd :- points to the last byte of the operand */
1055 /*-----------------------------------------------------------------*/
1057 pointToEnd (asmop * aop)
1063 aop->coff = count = (aop->size - 1);
1069 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1073 emitcode ("inc", "dptr");
1080 /*-----------------------------------------------------------------*/
1081 /* reAdjustPreg - points a register back to where it should */
1082 /*-----------------------------------------------------------------*/
1084 reAdjustPreg (asmop * aop)
1086 if ((aop->coff==0) || aop->size <= 1)
1094 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1099 emitcode ("lcall", "__decdptr");
1106 #define AOP(op) op->aop
1107 #define AOP_TYPE(op) AOP(op)->type
1108 #define AOP_SIZE(op) AOP(op)->size
1109 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1110 AOP_TYPE(x) == AOP_R0))
1112 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1113 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1115 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1116 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1117 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1119 /*-----------------------------------------------------------------*/
1120 /* genNotFloat - generates not for float operations */
1121 /*-----------------------------------------------------------------*/
1123 genNotFloat (operand * op, operand * res)
1129 /* we will put 127 in the first byte of
1131 aopPut (AOP (res), "#127", 0);
1132 size = AOP_SIZE (op) - 1;
1135 l = aopGet (op->aop, offset++, FALSE, FALSE);
1140 emitcode ("orl", "a,%s",
1142 offset++, FALSE, FALSE));
1145 tlbl = newiTempLabel (NULL);
1146 aopPut (res->aop, one, 1);
1147 emitcode ("jz", "%05d$", (tlbl->key + 100));
1148 aopPut (res->aop, zero, 1);
1149 emitcode ("", "%05d$:", (tlbl->key + 100));
1151 size = res->aop->size - 2;
1153 /* put zeros in the rest */
1155 aopPut (res->aop, zero, offset++);
1158 /*-----------------------------------------------------------------*/
1159 /* opIsGptr: returns non-zero if the passed operand is */
1160 /* a generic pointer type. */
1161 /*-----------------------------------------------------------------*/
1163 opIsGptr (operand * op)
1165 sym_link *type = operandType (op);
1167 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1174 /*-----------------------------------------------------------------*/
1175 /* getDataSize - get the operand data size */
1176 /*-----------------------------------------------------------------*/
1178 getDataSize (operand * op)
1181 size = AOP_SIZE (op);
1182 if (size == GPTRSIZE)
1184 sym_link *type = operandType (op);
1185 if (IS_GENPTR (type))
1187 /* generic pointer; arithmetic operations
1188 * should ignore the high byte (pointer type).
1196 /*-----------------------------------------------------------------*/
1197 /* outAcc - output Acc */
1198 /*-----------------------------------------------------------------*/
1200 outAcc (operand * result)
1203 size = getDataSize (result);
1206 aopPut (AOP (result), "a", 0);
1209 /* unsigned or positive */
1212 aopPut (AOP (result), zero, offset++);
1217 /*-----------------------------------------------------------------*/
1218 /* outBitC - output a bit C */
1219 /*-----------------------------------------------------------------*/
1221 outBitC (operand * result)
1223 /* if the result is bit */
1224 if (AOP_TYPE (result) == AOP_CRY)
1225 aopPut (AOP (result), "c", 0);
1228 emitcode ("clr", "a");
1229 emitcode ("rlc", "a");
1234 /*-----------------------------------------------------------------*/
1235 /* toBoolean - emit code for orl a,operator(sizeop) */
1236 /*-----------------------------------------------------------------*/
1238 toBoolean (operand * oper)
1240 int size = AOP_SIZE (oper) - 1;
1242 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1244 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1248 /*-----------------------------------------------------------------*/
1249 /* genNot - generate code for ! operation */
1250 /*-----------------------------------------------------------------*/
1255 sym_link *optype = operandType (IC_LEFT (ic));
1257 /* assign asmOps to operand & result */
1258 aopOp (IC_LEFT (ic), ic, FALSE);
1259 aopOp (IC_RESULT (ic), ic, TRUE);
1261 /* if in bit space then a special case */
1262 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1264 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1265 emitcode ("cpl", "c");
1266 outBitC (IC_RESULT (ic));
1270 /* if type float then do float */
1271 if (IS_FLOAT (optype))
1273 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1277 toBoolean (IC_LEFT (ic));
1279 tlbl = newiTempLabel (NULL);
1280 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1281 emitcode ("", "%05d$:", tlbl->key + 100);
1282 outBitC (IC_RESULT (ic));
1285 /* release the aops */
1286 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* genCpl - generate code for complement */
1293 /*-----------------------------------------------------------------*/
1301 /* assign asmOps to operand & result */
1302 aopOp (IC_LEFT (ic), ic, FALSE);
1303 aopOp (IC_RESULT (ic), ic, TRUE);
1305 /* if both are in bit space then
1307 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1308 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1311 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1312 emitcode ("cpl", "c");
1313 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1317 size = AOP_SIZE (IC_RESULT (ic));
1320 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1322 emitcode ("cpl", "a");
1323 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1328 /* release the aops */
1329 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1333 /*-----------------------------------------------------------------*/
1334 /* genUminusFloat - unary minus for floating points */
1335 /*-----------------------------------------------------------------*/
1337 genUminusFloat (operand * op, operand * result)
1339 int size, offset = 0;
1341 /* for this we just need to flip the
1342 first it then copy the rest in place */
1343 size = AOP_SIZE (op) - 1;
1344 l = aopGet (AOP (op), 3, FALSE, FALSE);
1348 emitcode ("cpl", "acc.7");
1349 aopPut (AOP (result), "a", 3);
1353 aopPut (AOP (result),
1354 aopGet (AOP (op), offset, FALSE, FALSE),
1360 /*-----------------------------------------------------------------*/
1361 /* genUminus - unary minus code generation */
1362 /*-----------------------------------------------------------------*/
1364 genUminus (iCode * ic)
1367 sym_link *optype, *rtype;
1371 aopOp (IC_LEFT (ic), ic, FALSE);
1372 aopOp (IC_RESULT (ic), ic, TRUE);
1374 /* if both in bit space then special
1376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1377 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1380 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1381 emitcode ("cpl", "c");
1382 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1386 optype = operandType (IC_LEFT (ic));
1387 rtype = operandType (IC_RESULT (ic));
1389 /* if float then do float stuff */
1390 if (IS_FLOAT (optype))
1392 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1396 /* otherwise subtract from zero */
1397 size = AOP_SIZE (IC_LEFT (ic));
1402 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1403 if (!strcmp (l, "a"))
1407 emitcode ("cpl", "a");
1408 emitcode ("addc", "a,#0");
1414 emitcode ("clr", "a");
1415 emitcode ("subb", "a,%s", l);
1417 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1420 /* if any remaining bytes in the result */
1421 /* we just need to propagate the sign */
1422 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1424 emitcode ("rlc", "a");
1425 emitcode ("subb", "a,acc");
1427 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1431 /* release the aops */
1432 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* saveRegisters - will look for a call and save the registers */
1438 /*-----------------------------------------------------------------*/
1440 saveRegisters (iCode * lic)
1447 for (ic = lic; ic; ic = ic->next)
1448 if (ic->op == CALL || ic->op == PCALL)
1453 fprintf (stderr, "found parameter push with no function call\n");
1457 /* if the registers have been saved already or don't need to be then
1459 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1460 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1463 /* safe the registers in use at this time but skip the
1464 ones for the result */
1465 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1466 mcs51_rUmaskForOp (IC_RESULT(ic)));
1469 if (options.useXstack)
1471 if (bitVectBitValue (rsave, R0_IDX))
1472 emitcode ("mov", "b,r0");
1473 emitcode ("mov", "r0,%s", spname);
1474 for (i = 0; i < mcs51_nRegs; i++)
1476 if (bitVectBitValue (rsave, i))
1479 emitcode ("mov", "a,b");
1481 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1482 emitcode ("movx", "@r0,a");
1483 emitcode ("inc", "r0");
1486 emitcode ("mov", "%s,r0", spname);
1487 if (bitVectBitValue (rsave, R0_IDX))
1488 emitcode ("mov", "r0,b");
1491 for (i = 0; i < mcs51_nRegs; i++)
1493 if (bitVectBitValue (rsave, i))
1494 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1498 /*-----------------------------------------------------------------*/
1499 /* unsaveRegisters - pop the pushed registers */
1500 /*-----------------------------------------------------------------*/
1502 unsaveRegisters (iCode * ic)
1507 /* restore the registers in use at this time but skip the
1508 ones for the result */
1509 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1510 mcs51_rUmaskForOp (IC_RESULT(ic)));
1512 if (options.useXstack)
1514 emitcode ("mov", "r0,%s", spname);
1515 for (i = mcs51_nRegs; i >= 0; i--)
1517 if (bitVectBitValue (rsave, i))
1519 emitcode ("dec", "r0");
1520 emitcode ("movx", "a,@r0");
1522 emitcode ("mov", "b,a");
1524 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1528 emitcode ("mov", "%s,r0", spname);
1529 if (bitVectBitValue (rsave, R0_IDX))
1530 emitcode ("mov", "r0,b");
1533 for (i = mcs51_nRegs; i >= 0; i--)
1535 if (bitVectBitValue (rsave, i))
1536 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1542 /*-----------------------------------------------------------------*/
1544 /*-----------------------------------------------------------------*/
1546 pushSide (operand * oper, int size)
1551 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1552 if (AOP_TYPE (oper) != AOP_REG &&
1553 AOP_TYPE (oper) != AOP_DIR &&
1556 emitcode ("mov", "a,%s", l);
1557 emitcode ("push", "acc");
1560 emitcode ("push", "%s", l);
1564 /*-----------------------------------------------------------------*/
1565 /* assignResultValue - */
1566 /*-----------------------------------------------------------------*/
1568 assignResultValue (operand * oper)
1571 int size = AOP_SIZE (oper);
1574 aopPut (AOP (oper), fReturn[offset], offset);
1580 /*-----------------------------------------------------------------*/
1581 /* genXpush - pushes onto the external stack */
1582 /*-----------------------------------------------------------------*/
1584 genXpush (iCode * ic)
1586 asmop *aop = newAsmop (0);
1588 int size, offset = 0;
1590 aopOp (IC_LEFT (ic), ic, FALSE);
1591 r = getFreePtr (ic, &aop, FALSE);
1594 emitcode ("mov", "%s,_spx", r->name);
1596 size = AOP_SIZE (IC_LEFT (ic));
1600 char *l = aopGet (AOP (IC_LEFT (ic)),
1601 offset++, FALSE, FALSE);
1603 emitcode ("movx", "@%s,a", r->name);
1604 emitcode ("inc", "%s", r->name);
1609 emitcode ("mov", "_spx,%s", r->name);
1611 freeAsmop (NULL, aop, ic, TRUE);
1612 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genIpush - genrate code for pushing this gets a little complex */
1617 /*-----------------------------------------------------------------*/
1619 genIpush (iCode * ic)
1621 int size, offset = 0;
1624 D(emitcode (";", "genIpush"));
1626 /* if this is not a parm push : ie. it is spill push
1627 and spill push is always done on the local stack */
1631 /* and the item is spilt then do nothing */
1632 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1635 aopOp (IC_LEFT (ic), ic, FALSE);
1636 size = AOP_SIZE (IC_LEFT (ic));
1637 /* push it on the stack */
1640 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1646 emitcode ("push", "%s", l);
1651 /* this is a paramter push: in this case we call
1652 the routine to find the call and save those
1653 registers that need to be saved */
1656 /* if use external stack then call the external
1657 stack pushing routine */
1658 if (options.useXstack)
1664 /* then do the push */
1665 aopOp (IC_LEFT (ic), ic, FALSE);
1668 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1669 size = AOP_SIZE (IC_LEFT (ic));
1673 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1674 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1675 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1678 emitcode ("mov", "a,%s", l);
1679 emitcode ("push", "acc");
1682 emitcode ("push", "%s", l);
1685 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1688 /*-----------------------------------------------------------------*/
1689 /* genIpop - recover the registers: can happen only for spilling */
1690 /*-----------------------------------------------------------------*/
1692 genIpop (iCode * ic)
1697 /* if the temp was not pushed then */
1698 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1701 aopOp (IC_LEFT (ic), ic, FALSE);
1702 size = AOP_SIZE (IC_LEFT (ic));
1703 offset = (size - 1);
1705 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1708 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1711 /*-----------------------------------------------------------------*/
1712 /* unsaveRBank - restores the resgister bank from stack */
1713 /*-----------------------------------------------------------------*/
1715 unsaveRBank (int bank, iCode * ic, bool popPsw)
1721 if (options.useXstack)
1725 /* Assume r0 is available for use. */
1726 r = mcs51_regWithIdx (R0_IDX);;
1731 r = getFreePtr (ic, &aop, FALSE);
1733 emitcode ("mov", "%s,_spx", r->name);
1738 if (options.useXstack)
1740 emitcode ("movx", "a,@%s", r->name);
1741 emitcode ("mov", "psw,a");
1742 emitcode ("dec", "%s", r->name);
1746 emitcode ("pop", "psw");
1750 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1752 if (options.useXstack)
1754 emitcode ("movx", "a,@%s", r->name);
1755 emitcode ("mov", "(%s+%d),a",
1756 regs8051[i].base, 8 * bank + regs8051[i].offset);
1757 emitcode ("dec", "%s", r->name);
1761 emitcode ("pop", "(%s+%d)",
1762 regs8051[i].base, 8 * bank + regs8051[i].offset);
1765 if (options.useXstack)
1767 emitcode ("mov", "_spx,%s", r->name);
1772 freeAsmop (NULL, aop, ic, TRUE);
1776 /*-----------------------------------------------------------------*/
1777 /* saveRBank - saves an entire register bank on the stack */
1778 /*-----------------------------------------------------------------*/
1780 saveRBank (int bank, iCode * ic, bool pushPsw)
1786 if (options.useXstack)
1790 /* Assume r0 is available for use. */
1791 r = mcs51_regWithIdx (R0_IDX);;
1796 r = getFreePtr (ic, &aop, FALSE);
1798 emitcode ("mov", "%s,_spx", r->name);
1801 for (i = 0; i < mcs51_nRegs; i++)
1803 if (options.useXstack)
1805 emitcode ("inc", "%s", r->name);
1806 emitcode ("mov", "a,(%s+%d)",
1807 regs8051[i].base, 8 * bank + regs8051[i].offset);
1808 emitcode ("movx", "@%s,a", r->name);
1811 emitcode ("push", "(%s+%d)",
1812 regs8051[i].base, 8 * bank + regs8051[i].offset);
1817 if (options.useXstack)
1819 emitcode ("mov", "a,psw");
1820 emitcode ("movx", "@%s,a", r->name);
1821 emitcode ("inc", "%s", r->name);
1822 emitcode ("mov", "_spx,%s", r->name);
1827 emitcode ("push", "psw");
1830 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1835 freeAsmop (NULL, aop, ic, TRUE);
1844 /*-----------------------------------------------------------------*/
1845 /* genCall - generates a call statement */
1846 /*-----------------------------------------------------------------*/
1848 genCall (iCode * ic)
1851 bool restoreBank = FALSE;
1852 bool swapBanks = FALSE;
1854 D(emitcode(";", "genCall"));
1855 /* if send set is not empty the assign */
1860 for (sic = setFirstItem (_G.sendSet); sic;
1861 sic = setNextItem (_G.sendSet))
1863 int size, offset = 0;
1864 aopOp (IC_LEFT (sic), sic, FALSE);
1865 size = AOP_SIZE (IC_LEFT (sic));
1868 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1870 if (strcmp (l, fReturn[offset]))
1871 emitcode ("mov", "%s,%s",
1876 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1881 /* if we are calling a not _naked function that is not using
1882 the same register bank then we need to save the
1883 destination registers on the stack */
1884 dtype = operandType (IC_LEFT (ic));
1885 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1886 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1887 IFFUNC_ISISR (currFunc->type))
1891 /* This is unexpected; the bank should have been saved in
1894 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1900 /* if caller saves & we have not saved then */
1906 emitcode ("mov", "psw,#0x%02x",
1907 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1911 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1912 OP_SYMBOL (IC_LEFT (ic))->rname :
1913 OP_SYMBOL (IC_LEFT (ic))->name));
1917 emitcode ("mov", "psw,#0x%02x",
1918 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1921 /* if we need assign a result value */
1922 if ((IS_ITEMP (IC_RESULT (ic)) &&
1923 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1924 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1925 IS_TRUE_SYMOP (IC_RESULT (ic)))
1929 aopOp (IC_RESULT (ic), ic, FALSE);
1932 assignResultValue (IC_RESULT (ic));
1934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1937 /* adjust the stack for parameters if
1942 if (ic->parmBytes > 3)
1944 emitcode ("mov", "a,%s", spname);
1945 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1946 emitcode ("mov", "%s,a", spname);
1949 for (i = 0; i < ic->parmBytes; i++)
1950 emitcode ("dec", "%s", spname);
1953 /* if we hade saved some registers then unsave them */
1954 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1955 unsaveRegisters (ic);
1957 /* if register bank was saved then pop them */
1959 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1962 /*-----------------------------------------------------------------*/
1963 /* genPcall - generates a call by pointer statement */
1964 /*-----------------------------------------------------------------*/
1966 genPcall (iCode * ic)
1969 symbol *rlbl = newiTempLabel (NULL);
1971 D(emitcode(";", "genPCall"));
1972 /* if caller saves & we have not saved then */
1976 /* if we are calling a function that is not using
1977 the same register bank then we need to save the
1978 destination registers on the stack */
1979 dtype = operandType (IC_LEFT (ic));
1981 IFFUNC_ISISR (currFunc->type) &&
1982 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
1983 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
1986 /* push the return address on to the stack */
1987 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1988 emitcode ("push", "acc");
1989 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1990 emitcode ("push", "acc");
1992 /* now push the calling address */
1993 aopOp (IC_LEFT (ic), ic, FALSE);
1995 pushSide (IC_LEFT (ic), FPTRSIZE);
1997 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1999 /* if send set is not empty the assign */
2004 for (sic = setFirstItem (_G.sendSet); sic;
2005 sic = setNextItem (_G.sendSet))
2007 int size, offset = 0;
2008 aopOp (IC_LEFT (sic), sic, FALSE);
2009 size = AOP_SIZE (IC_LEFT (sic));
2012 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2014 if (strcmp (l, fReturn[offset]))
2015 emitcode ("mov", "%s,%s",
2020 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2025 emitcode ("ret", "");
2026 emitcode ("", "%05d$:", (rlbl->key + 100));
2029 /* if we need assign a result value */
2030 if ((IS_ITEMP (IC_RESULT (ic)) &&
2031 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2032 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2033 IS_TRUE_SYMOP (IC_RESULT (ic)))
2037 aopOp (IC_RESULT (ic), ic, FALSE);
2040 assignResultValue (IC_RESULT (ic));
2042 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2045 /* adjust the stack for parameters if
2050 if (ic->parmBytes > 3)
2052 emitcode ("mov", "a,%s", spname);
2053 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2054 emitcode ("mov", "%s,a", spname);
2057 for (i = 0; i < ic->parmBytes; i++)
2058 emitcode ("dec", "%s", spname);
2062 /* if register bank was saved then unsave them */
2064 (FUNC_REGBANK (currFunc->type) !=
2065 FUNC_REGBANK (dtype)))
2066 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2068 /* if we hade saved some registers then
2071 unsaveRegisters (ic);
2074 /*-----------------------------------------------------------------*/
2075 /* resultRemat - result is rematerializable */
2076 /*-----------------------------------------------------------------*/
2078 resultRemat (iCode * ic)
2080 if (SKIP_IC (ic) || ic->op == IFX)
2083 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2085 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2086 if (sym->remat && !POINTER_SET (ic))
2093 #if defined(__BORLANDC__) || defined(_MSC_VER)
2094 #define STRCASECMP stricmp
2096 #define STRCASECMP strcasecmp
2099 /*-----------------------------------------------------------------*/
2100 /* inExcludeList - return 1 if the string is in exclude Reg list */
2101 /*-----------------------------------------------------------------*/
2103 inExcludeList (char *s)
2107 if (options.excludeRegs[i] &&
2108 STRCASECMP (options.excludeRegs[i], "none") == 0)
2111 for (i = 0; options.excludeRegs[i]; i++)
2113 if (options.excludeRegs[i] &&
2114 STRCASECMP (s, options.excludeRegs[i]) == 0)
2120 /*-----------------------------------------------------------------*/
2121 /* genFunction - generated code for function entry */
2122 /*-----------------------------------------------------------------*/
2124 genFunction (iCode * ic)
2128 bool switchedPSW = FALSE;
2131 /* create the function header */
2132 emitcode (";", "-----------------------------------------");
2133 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2134 emitcode (";", "-----------------------------------------");
2136 emitcode ("", "%s:", sym->rname);
2137 ftype = operandType (IC_LEFT (ic));
2139 if (IFFUNC_ISNAKED(ftype))
2141 emitcode(";", "naked function: no prologue.");
2145 /* if critical function then turn interrupts off */
2146 if (IFFUNC_ISCRITICAL (ftype))
2147 emitcode ("clr", "ea");
2149 /* here we need to generate the equates for the
2150 register bank if required */
2151 if (FUNC_REGBANK (ftype) != rbank)
2155 rbank = FUNC_REGBANK (ftype);
2156 for (i = 0; i < mcs51_nRegs; i++)
2158 if (strcmp (regs8051[i].base, "0") == 0)
2159 emitcode ("", "%s = 0x%02x",
2161 8 * rbank + regs8051[i].offset);
2163 emitcode ("", "%s = %s + 0x%02x",
2166 8 * rbank + regs8051[i].offset);
2170 /* if this is an interrupt service routine then
2171 save acc, b, dpl, dph */
2172 if (IFFUNC_ISISR (sym->type))
2175 if (!inExcludeList ("acc"))
2176 emitcode ("push", "acc");
2177 if (!inExcludeList ("b"))
2178 emitcode ("push", "b");
2179 if (!inExcludeList ("dpl"))
2180 emitcode ("push", "dpl");
2181 if (!inExcludeList ("dph"))
2182 emitcode ("push", "dph");
2183 /* if this isr has no bank i.e. is going to
2184 run with bank 0 , then we need to save more
2186 if (!FUNC_REGBANK (sym->type))
2189 /* if this function does not call any other
2190 function then we can be economical and
2191 save only those registers that are used */
2192 if (!IFFUNC_HASFCALL(sym->type))
2196 /* if any registers used */
2199 /* save the registers used */
2200 for (i = 0; i < sym->regsUsed->size; i++)
2202 if (bitVectBitValue (sym->regsUsed, i) ||
2203 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2204 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2211 /* this function has a function call cannot
2212 determines register usage so we will have to push the
2214 saveRBank (0, ic, FALSE);
2219 /* This ISR uses a non-zero bank.
2221 * We assume that the bank is available for our
2224 * However, if this ISR calls a function which uses some
2225 * other bank, we must save that bank entirely.
2227 unsigned long banksToSave = 0;
2229 if (IFFUNC_HASFCALL(sym->type))
2232 #define MAX_REGISTER_BANKS 4
2237 for (i = ic; i; i = i->next)
2239 if (i->op == ENDFUNCTION)
2241 /* we got to the end OK. */
2249 dtype = operandType (IC_LEFT(i));
2251 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2253 /* Mark this bank for saving. */
2254 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2256 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2260 banksToSave |= (1 << FUNC_REGBANK(dtype));
2263 /* And note that we don't need to do it in
2271 /* This is a mess; we have no idea what
2272 * register bank the called function might
2275 * The only thing I can think of to do is
2276 * throw a warning and hope.
2278 werror(W_FUNCPTR_IN_USING_ISR);
2282 if (banksToSave && options.useXstack)
2284 /* Since we aren't passing it an ic,
2285 * saveRBank will assume r0 is available to abuse.
2287 * So switch to our (trashable) bank now, so
2288 * the caller's R0 isn't trashed.
2290 emitcode ("push", "psw");
2291 emitcode ("mov", "psw,#0x%02x",
2292 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2296 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2298 if (banksToSave & (1 << ix))
2300 saveRBank(ix, NULL, FALSE);
2304 // jwk: this needs a closer look
2305 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2310 /* if callee-save to be used for this function
2311 then save the registers being used in this function */
2312 if (IFFUNC_CALLEESAVES(sym->type))
2316 /* if any registers used */
2319 /* save the registers used */
2320 for (i = 0; i < sym->regsUsed->size; i++)
2322 if (bitVectBitValue (sym->regsUsed, i) ||
2323 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2325 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2333 /* set the register bank to the desired value */
2334 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2337 emitcode ("push", "psw");
2338 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2341 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2344 if (options.useXstack)
2346 emitcode ("mov", "r0,%s", spname);
2347 emitcode ("mov", "a,_bp");
2348 emitcode ("movx", "@r0,a");
2349 emitcode ("inc", "%s", spname);
2353 /* set up the stack */
2354 emitcode ("push", "_bp"); /* save the callers stack */
2356 emitcode ("mov", "_bp,%s", spname);
2359 /* adjust the stack for the function */
2365 werror (W_STACK_OVERFLOW, sym->name);
2367 if (i > 3 && sym->recvSize < 4)
2370 emitcode ("mov", "a,sp");
2371 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2372 emitcode ("mov", "sp,a");
2377 emitcode ("inc", "sp");
2383 emitcode ("mov", "a,_spx");
2384 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2385 emitcode ("mov", "_spx,a");
2390 /*-----------------------------------------------------------------*/
2391 /* genEndFunction - generates epilogue for functions */
2392 /*-----------------------------------------------------------------*/
2394 genEndFunction (iCode * ic)
2396 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2398 if (IFFUNC_ISNAKED(sym->type))
2400 emitcode(";", "naked function: no epilogue.");
2404 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2406 emitcode ("mov", "%s,_bp", spname);
2409 /* if use external stack but some variables were
2410 added to the local stack then decrement the
2412 if (options.useXstack && sym->stack)
2414 emitcode ("mov", "a,sp");
2415 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2416 emitcode ("mov", "sp,a");
2420 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2422 if (options.useXstack)
2424 emitcode ("mov", "r0,%s", spname);
2425 emitcode ("movx", "a,@r0");
2426 emitcode ("mov", "_bp,a");
2427 emitcode ("dec", "%s", spname);
2431 emitcode ("pop", "_bp");
2435 /* restore the register bank */
2436 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2438 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2439 || !options.useXstack)
2441 /* Special case of ISR using non-zero bank with useXstack
2444 emitcode ("pop", "psw");
2448 if (IFFUNC_ISISR (sym->type))
2451 /* now we need to restore the registers */
2452 /* if this isr has no bank i.e. is going to
2453 run with bank 0 , then we need to save more
2455 if (!FUNC_REGBANK (sym->type))
2457 /* if this function does not call any other
2458 function then we can be economical and
2459 save only those registers that are used */
2460 if (!IFFUNC_HASFCALL(sym->type))
2464 /* if any registers used */
2467 /* save the registers used */
2468 for (i = sym->regsUsed->size; i >= 0; i--)
2470 if (bitVectBitValue (sym->regsUsed, i) ||
2471 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2472 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2479 /* this function has a function call cannot
2480 determines register usage so we will have to pop the
2482 unsaveRBank (0, ic, FALSE);
2487 /* This ISR uses a non-zero bank.
2489 * Restore any register banks saved by genFunction
2492 // jwk: this needs a closer look
2493 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2496 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2498 if (savedBanks & (1 << ix))
2500 unsaveRBank(ix, NULL, FALSE);
2504 if (options.useXstack)
2506 /* Restore bank AFTER calling unsaveRBank,
2507 * since it can trash r0.
2509 emitcode ("pop", "psw");
2513 if (!inExcludeList ("dph"))
2514 emitcode ("pop", "dph");
2515 if (!inExcludeList ("dpl"))
2516 emitcode ("pop", "dpl");
2517 if (!inExcludeList ("b"))
2518 emitcode ("pop", "b");
2519 if (!inExcludeList ("acc"))
2520 emitcode ("pop", "acc");
2522 if (IFFUNC_ISCRITICAL (sym->type))
2523 emitcode ("setb", "ea");
2525 /* if debug then send end of function */
2526 /* if (options.debug && currFunc) */
2527 if (options.debug && currFunc)
2530 emitcode ("", "C$%s$%d$%d$%d ==.",
2531 FileBaseName (ic->filename), currFunc->lastLine,
2532 ic->level, ic->block);
2533 if (IS_STATIC (currFunc->etype))
2534 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2536 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2540 emitcode ("reti", "");
2544 if (IFFUNC_ISCRITICAL (sym->type))
2545 emitcode ("setb", "ea");
2547 if (IFFUNC_CALLEESAVES(sym->type))
2551 /* if any registers used */
2554 /* save the registers used */
2555 for (i = sym->regsUsed->size; i >= 0; i--)
2557 if (bitVectBitValue (sym->regsUsed, i) ||
2558 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2559 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2565 /* if debug then send end of function */
2566 if (options.debug && currFunc)
2569 emitcode ("", "C$%s$%d$%d$%d ==.",
2570 FileBaseName (ic->filename), currFunc->lastLine,
2571 ic->level, ic->block);
2572 if (IS_STATIC (currFunc->etype))
2573 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2575 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2579 emitcode ("ret", "");
2584 /*-----------------------------------------------------------------*/
2585 /* genRet - generate code for return statement */
2586 /*-----------------------------------------------------------------*/
2590 int size, offset = 0, pushed = 0;
2592 /* if we have no return value then
2593 just generate the "ret" */
2597 /* we have something to return then
2598 move the return value into place */
2599 aopOp (IC_LEFT (ic), ic, FALSE);
2600 size = AOP_SIZE (IC_LEFT (ic));
2605 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2608 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2610 emitcode ("push", "%s", l);
2615 l = aopGet (AOP (IC_LEFT (ic)), offset,
2617 if (strcmp (fReturn[offset], l))
2618 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2627 if (strcmp (fReturn[pushed], "a"))
2628 emitcode ("pop", fReturn[pushed]);
2630 emitcode ("pop", "acc");
2633 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2636 /* generate a jump to the return label
2637 if the next is not the return statement */
2638 if (!(ic->next && ic->next->op == LABEL &&
2639 IC_LABEL (ic->next) == returnLabel))
2641 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2645 /*-----------------------------------------------------------------*/
2646 /* genLabel - generates a label */
2647 /*-----------------------------------------------------------------*/
2649 genLabel (iCode * ic)
2651 /* special case never generate */
2652 if (IC_LABEL (ic) == entryLabel)
2655 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2658 /*-----------------------------------------------------------------*/
2659 /* genGoto - generates a ljmp */
2660 /*-----------------------------------------------------------------*/
2662 genGoto (iCode * ic)
2664 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2667 /*-----------------------------------------------------------------*/
2668 /* findLabelBackwards: walks back through the iCode chain looking */
2669 /* for the given label. Returns number of iCode instructions */
2670 /* between that label and given ic. */
2671 /* Returns zero if label not found. */
2672 /*-----------------------------------------------------------------*/
2674 findLabelBackwards (iCode * ic, int key)
2683 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2685 /* printf("findLabelBackwards = %d\n", count); */
2693 /*-----------------------------------------------------------------*/
2694 /* genPlusIncr :- does addition with increment if possible */
2695 /*-----------------------------------------------------------------*/
2697 genPlusIncr (iCode * ic)
2699 unsigned int icount;
2700 unsigned int size = getDataSize (IC_RESULT (ic));
2702 /* will try to generate an increment */
2703 /* if the right side is not a literal
2705 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2708 /* if the literal value of the right hand side
2709 is greater than 4 then it is not worth it */
2710 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2713 /* if increment 16 bits in register */
2714 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2722 /* If the next instruction is a goto and the goto target
2723 * is < 10 instructions previous to this, we can generate
2724 * jumps straight to that target.
2726 if (ic->next && ic->next->op == GOTO
2727 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2728 && labelRange <= 10)
2730 emitcode (";", "tail increment optimized");
2731 tlbl = IC_LABEL (ic->next);
2736 tlbl = newiTempLabel (NULL);
2739 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2740 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2741 IS_AOP_PREG (IC_RESULT (ic)))
2742 emitcode ("cjne", "%s,#0x00,%05d$"
2743 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2747 emitcode ("clr", "a");
2748 emitcode ("cjne", "a,%s,%05d$"
2749 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2753 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2756 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2757 IS_AOP_PREG (IC_RESULT (ic)))
2758 emitcode ("cjne", "%s,#0x00,%05d$"
2759 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2762 emitcode ("cjne", "a,%s,%05d$"
2763 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2766 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2770 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2771 IS_AOP_PREG (IC_RESULT (ic)))
2772 emitcode ("cjne", "%s,#0x00,%05d$"
2773 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2777 emitcode ("cjne", "a,%s,%05d$"
2778 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2781 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2786 emitcode ("", "%05d$:", tlbl->key + 100);
2791 /* if the sizes are greater than 1 then we cannot */
2792 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2793 AOP_SIZE (IC_LEFT (ic)) > 1)
2796 /* we can if the aops of the left & result match or
2797 if they are in registers and the registers are the
2799 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2804 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2805 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2806 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2812 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2821 /*-----------------------------------------------------------------*/
2822 /* outBitAcc - output a bit in acc */
2823 /*-----------------------------------------------------------------*/
2825 outBitAcc (operand * result)
2827 symbol *tlbl = newiTempLabel (NULL);
2828 /* if the result is a bit */
2829 if (AOP_TYPE (result) == AOP_CRY)
2831 aopPut (AOP (result), "a", 0);
2835 emitcode ("jz", "%05d$", tlbl->key + 100);
2836 emitcode ("mov", "a,%s", one);
2837 emitcode ("", "%05d$:", tlbl->key + 100);
2842 /*-----------------------------------------------------------------*/
2843 /* genPlusBits - generates code for addition of two bits */
2844 /*-----------------------------------------------------------------*/
2846 genPlusBits (iCode * ic)
2848 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2850 symbol *lbl = newiTempLabel (NULL);
2851 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2852 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2853 emitcode ("cpl", "c");
2854 emitcode ("", "%05d$:", (lbl->key + 100));
2855 outBitC (IC_RESULT (ic));
2859 emitcode ("clr", "a");
2860 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2861 emitcode ("rlc", "a");
2862 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2863 emitcode ("addc", "a,#0x00");
2864 outAcc (IC_RESULT (ic));
2869 /* This is the original version of this code.
2871 * This is being kept around for reference,
2872 * because I am not entirely sure I got it right...
2875 adjustArithmeticResult (iCode * ic)
2877 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2878 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2879 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2880 aopPut (AOP (IC_RESULT (ic)),
2881 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2884 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2885 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2886 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2887 aopPut (AOP (IC_RESULT (ic)),
2888 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2891 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2892 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2893 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2894 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2895 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2898 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2899 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2903 /* This is the pure and virtuous version of this code.
2904 * I'm pretty certain it's right, but not enough to toss the old
2908 adjustArithmeticResult (iCode * ic)
2910 if (opIsGptr (IC_RESULT (ic)) &&
2911 opIsGptr (IC_LEFT (ic)) &&
2912 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2914 aopPut (AOP (IC_RESULT (ic)),
2915 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2919 if (opIsGptr (IC_RESULT (ic)) &&
2920 opIsGptr (IC_RIGHT (ic)) &&
2921 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2923 aopPut (AOP (IC_RESULT (ic)),
2924 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2928 if (opIsGptr (IC_RESULT (ic)) &&
2929 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2930 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2931 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2932 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2935 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2936 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2941 /*-----------------------------------------------------------------*/
2942 /* genPlus - generates code for addition */
2943 /*-----------------------------------------------------------------*/
2945 genPlus (iCode * ic)
2947 int size, offset = 0;
2949 /* special cases :- */
2951 aopOp (IC_LEFT (ic), ic, FALSE);
2952 aopOp (IC_RIGHT (ic), ic, FALSE);
2953 aopOp (IC_RESULT (ic), ic, TRUE);
2955 /* if literal, literal on the right or
2956 if left requires ACC or right is already
2958 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2959 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2960 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2962 operand *t = IC_RIGHT (ic);
2963 IC_RIGHT (ic) = IC_LEFT (ic);
2967 /* if both left & right are in bit
2969 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2970 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2976 /* if left in bit space & right literal */
2977 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2978 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2980 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2981 /* if result in bit space */
2982 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2984 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2985 emitcode ("cpl", "c");
2986 outBitC (IC_RESULT (ic));
2990 size = getDataSize (IC_RESULT (ic));
2993 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2994 emitcode ("addc", "a,#00");
2995 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3001 /* if I can do an increment instead
3002 of add then GOOD for ME */
3003 if (genPlusIncr (ic) == TRUE)
3006 size = getDataSize (IC_RESULT (ic));
3010 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3012 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3014 emitcode ("add", "a,%s",
3015 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3017 emitcode ("addc", "a,%s",
3018 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3022 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3024 emitcode ("add", "a,%s",
3025 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3027 emitcode ("addc", "a,%s",
3028 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3030 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3033 adjustArithmeticResult (ic);
3036 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3037 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3041 /*-----------------------------------------------------------------*/
3042 /* genMinusDec :- does subtraction with deccrement if possible */
3043 /*-----------------------------------------------------------------*/
3045 genMinusDec (iCode * ic)
3047 unsigned int icount;
3048 unsigned int size = getDataSize (IC_RESULT (ic));
3050 /* will try to generate an increment */
3051 /* if the right side is not a literal
3053 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3056 /* if the literal value of the right hand side
3057 is greater than 4 then it is not worth it */
3058 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3061 /* if decrement 16 bits in register */
3062 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3070 /* If the next instruction is a goto and the goto target
3071 * is <= 10 instructions previous to this, we can generate
3072 * jumps straight to that target.
3074 if (ic->next && ic->next->op == GOTO
3075 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3076 && labelRange <= 10)
3078 emitcode (";", "tail decrement optimized");
3079 tlbl = IC_LABEL (ic->next);
3084 tlbl = newiTempLabel (NULL);
3088 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3089 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3090 IS_AOP_PREG (IC_RESULT (ic)))
3091 emitcode ("cjne", "%s,#0xff,%05d$"
3092 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3096 emitcode ("mov", "a,#0xff");
3097 emitcode ("cjne", "a,%s,%05d$"
3098 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3101 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3104 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3105 IS_AOP_PREG (IC_RESULT (ic)))
3106 emitcode ("cjne", "%s,#0xff,%05d$"
3107 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3111 emitcode ("cjne", "a,%s,%05d$"
3112 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3115 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3119 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3120 IS_AOP_PREG (IC_RESULT (ic)))
3121 emitcode ("cjne", "%s,#0xff,%05d$"
3122 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3126 emitcode ("cjne", "a,%s,%05d$"
3127 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3130 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3134 emitcode ("", "%05d$:", tlbl->key + 100);
3139 /* if the sizes are greater than 1 then we cannot */
3140 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3141 AOP_SIZE (IC_LEFT (ic)) > 1)
3144 /* we can if the aops of the left & result match or
3145 if they are in registers and the registers are the
3147 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3151 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3159 /*-----------------------------------------------------------------*/
3160 /* addSign - complete with sign */
3161 /*-----------------------------------------------------------------*/
3163 addSign (operand * result, int offset, int sign)
3165 int size = (getDataSize (result) - offset);
3170 emitcode ("rlc", "a");
3171 emitcode ("subb", "a,acc");
3173 aopPut (AOP (result), "a", offset++);
3177 aopPut (AOP (result), zero, offset++);
3181 /*-----------------------------------------------------------------*/
3182 /* genMinusBits - generates code for subtraction of two bits */
3183 /*-----------------------------------------------------------------*/
3185 genMinusBits (iCode * ic)
3187 symbol *lbl = newiTempLabel (NULL);
3188 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3190 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3191 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3192 emitcode ("cpl", "c");
3193 emitcode ("", "%05d$:", (lbl->key + 100));
3194 outBitC (IC_RESULT (ic));
3198 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3199 emitcode ("subb", "a,acc");
3200 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3201 emitcode ("inc", "a");
3202 emitcode ("", "%05d$:", (lbl->key + 100));
3203 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3204 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3208 /*-----------------------------------------------------------------*/
3209 /* genMinus - generates code for subtraction */
3210 /*-----------------------------------------------------------------*/
3212 genMinus (iCode * ic)
3214 int size, offset = 0;
3215 unsigned long lit = 0L;
3217 aopOp (IC_LEFT (ic), ic, FALSE);
3218 aopOp (IC_RIGHT (ic), ic, FALSE);
3219 aopOp (IC_RESULT (ic), ic, TRUE);
3221 /* special cases :- */
3222 /* if both left & right are in bit space */
3223 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3224 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3230 /* if I can do an decrement instead
3231 of subtract then GOOD for ME */
3232 if (genMinusDec (ic) == TRUE)
3235 size = getDataSize (IC_RESULT (ic));
3237 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3243 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3247 /* if literal, add a,#-lit, else normal subb */
3250 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3251 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3252 emitcode ("subb", "a,%s",
3253 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3256 /* first add without previous c */
3258 if (!size && lit==-1) {
3259 emitcode ("dec", "a");
3261 emitcode ("add", "a,#0x%02x",
3262 (unsigned int) (lit & 0x0FFL));
3265 emitcode ("addc", "a,#0x%02x",
3266 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3269 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3272 adjustArithmeticResult (ic);
3275 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3276 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3277 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3281 /*-----------------------------------------------------------------*/
3282 /* genMultbits :- multiplication of bits */
3283 /*-----------------------------------------------------------------*/
3285 genMultbits (operand * left,
3289 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3290 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3295 /*-----------------------------------------------------------------*/
3296 /* genMultOneByte : 8*8=8/16 bit multiplication */
3297 /*-----------------------------------------------------------------*/
3299 genMultOneByte (operand * left,
3303 sym_link *opetype = operandType (result);
3305 int size=AOP_SIZE(result);
3307 if (size<1 || size>2) {
3308 // this should never happen
3309 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3310 AOP_SIZE(result), __FILE__, lineno);
3314 /* (if two literals: the value is computed before) */
3315 /* if one literal, literal on the right */
3316 if (AOP_TYPE (left) == AOP_LIT)
3321 //emitcode (";", "swapped left and right");
3324 if (SPEC_USIGN(opetype)
3325 // ignore the sign of left and right, what else can we do?
3326 || (SPEC_USIGN(operandType(left)) &&
3327 SPEC_USIGN(operandType(right)))) {
3328 // just an unsigned 8*8=8/16 multiply
3329 //emitcode (";","unsigned");
3330 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3331 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3332 emitcode ("mul", "ab");
3333 aopPut (AOP (result), "a", 0);
3335 aopPut (AOP (result), "b", 1);
3340 // we have to do a signed multiply
3342 //emitcode (";", "signed");
3343 emitcode ("clr", "F0"); // reset sign flag
3344 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3346 lbl=newiTempLabel(NULL);
3347 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3348 // left side is negative, 8-bit two's complement, this fails for -128
3349 emitcode ("setb", "F0"); // set sign flag
3350 emitcode ("cpl", "a");
3351 emitcode ("inc", "a");
3353 emitcode ("", "%05d$:", lbl->key+100);
3356 if (AOP_TYPE(right)==AOP_LIT) {
3357 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3358 /* AND literal negative */
3360 emitcode ("cpl", "F0"); // complement sign flag
3361 emitcode ("mov", "b,#0x%02x", -val);
3363 emitcode ("mov", "b,#0x%02x", val);
3366 lbl=newiTempLabel(NULL);
3367 emitcode ("mov", "b,a");
3368 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3369 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3370 // right side is negative, 8-bit two's complement
3371 emitcode ("cpl", "F0"); // complement sign flag
3372 emitcode ("cpl", "a");
3373 emitcode ("inc", "a");
3374 emitcode ("", "%05d$:", lbl->key+100);
3376 emitcode ("mul", "ab");
3378 lbl=newiTempLabel(NULL);
3379 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3380 // only ONE op was negative, we have to do a 8/16-bit two's complement
3381 emitcode ("cpl", "a"); // lsb
3383 emitcode ("inc", "a");
3385 emitcode ("add", "a,#1");
3386 emitcode ("xch", "a,b");
3387 emitcode ("cpl", "a"); // msb
3388 emitcode ("addc", "a,#0");
3389 emitcode ("xch", "a,b");
3392 emitcode ("", "%05d$:", lbl->key+100);
3393 aopPut (AOP (result), "a", 0);
3395 aopPut (AOP (result), "b", 1);
3399 /*-----------------------------------------------------------------*/
3400 /* genMult - generates code for multiplication */
3401 /*-----------------------------------------------------------------*/
3403 genMult (iCode * ic)
3405 operand *left = IC_LEFT (ic);
3406 operand *right = IC_RIGHT (ic);
3407 operand *result = IC_RESULT (ic);
3409 /* assign the amsops */
3410 aopOp (left, ic, FALSE);
3411 aopOp (right, ic, FALSE);
3412 aopOp (result, ic, TRUE);
3414 /* special cases first */
3416 if (AOP_TYPE (left) == AOP_CRY &&
3417 AOP_TYPE (right) == AOP_CRY)
3419 genMultbits (left, right, result);
3423 /* if both are of size == 1 */
3424 #if 0 // one of them can be a sloc shared with the result
3425 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3427 if (getSize(operandType(left)) == 1 &&
3428 getSize(operandType(right)) == 1)
3431 genMultOneByte (left, right, result);
3435 /* should have been converted to function call */
3436 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3437 getSize(OP_SYMBOL(right)->type));
3441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3443 freeAsmop (result, NULL, ic, TRUE);
3446 /*-----------------------------------------------------------------*/
3447 /* genDivbits :- division of bits */
3448 /*-----------------------------------------------------------------*/
3450 genDivbits (operand * left,
3457 /* the result must be bit */
3458 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3459 l = aopGet (AOP (left), 0, FALSE, FALSE);
3463 emitcode ("div", "ab");
3464 emitcode ("rrc", "a");
3465 aopPut (AOP (result), "c", 0);
3468 /*-----------------------------------------------------------------*/
3469 /* genDivOneByte : 8 bit division */
3470 /*-----------------------------------------------------------------*/
3472 genDivOneByte (operand * left,
3476 sym_link *opetype = operandType (result);
3481 size = AOP_SIZE (result) - 1;
3483 /* signed or unsigned */
3484 if (SPEC_USIGN (opetype))
3486 /* unsigned is easy */
3487 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3488 l = aopGet (AOP (left), 0, FALSE, FALSE);
3490 emitcode ("div", "ab");
3491 aopPut (AOP (result), "a", 0);
3493 aopPut (AOP (result), zero, offset++);
3497 /* signed is a little bit more difficult */
3499 /* save the signs of the operands */
3500 l = aopGet (AOP (left), 0, FALSE, FALSE);
3502 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3503 emitcode ("push", "acc"); /* save it on the stack */
3505 /* now sign adjust for both left & right */
3506 l = aopGet (AOP (right), 0, FALSE, FALSE);
3508 lbl = newiTempLabel (NULL);
3509 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3510 emitcode ("cpl", "a");
3511 emitcode ("inc", "a");
3512 emitcode ("", "%05d$:", (lbl->key + 100));
3513 emitcode ("mov", "b,a");
3515 /* sign adjust left side */
3516 l = aopGet (AOP (left), 0, FALSE, FALSE);
3519 lbl = newiTempLabel (NULL);
3520 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3521 emitcode ("cpl", "a");
3522 emitcode ("inc", "a");
3523 emitcode ("", "%05d$:", (lbl->key + 100));
3525 /* now the division */
3526 emitcode ("div", "ab");
3527 /* we are interested in the lower order
3529 emitcode ("mov", "b,a");
3530 lbl = newiTempLabel (NULL);
3531 emitcode ("pop", "acc");
3532 /* if there was an over flow we don't
3533 adjust the sign of the result */
3534 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3535 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3537 emitcode ("clr", "a");
3538 emitcode ("subb", "a,b");
3539 emitcode ("mov", "b,a");
3540 emitcode ("", "%05d$:", (lbl->key + 100));
3542 /* now we are done */
3543 aopPut (AOP (result), "b", 0);
3546 emitcode ("mov", "c,b.7");
3547 emitcode ("subb", "a,acc");
3550 aopPut (AOP (result), "a", offset++);
3554 /*-----------------------------------------------------------------*/
3555 /* genDiv - generates code for division */
3556 /*-----------------------------------------------------------------*/
3560 operand *left = IC_LEFT (ic);
3561 operand *right = IC_RIGHT (ic);
3562 operand *result = IC_RESULT (ic);
3564 /* assign the amsops */
3565 aopOp (left, ic, FALSE);
3566 aopOp (right, ic, FALSE);
3567 aopOp (result, ic, TRUE);
3569 /* special cases first */
3571 if (AOP_TYPE (left) == AOP_CRY &&
3572 AOP_TYPE (right) == AOP_CRY)
3574 genDivbits (left, right, result);
3578 /* if both are of size == 1 */
3579 if (AOP_SIZE (left) == 1 &&
3580 AOP_SIZE (right) == 1)
3582 genDivOneByte (left, right, result);
3586 /* should have been converted to function call */
3589 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3590 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3591 freeAsmop (result, NULL, ic, TRUE);
3594 /*-----------------------------------------------------------------*/
3595 /* genModbits :- modulus of bits */
3596 /*-----------------------------------------------------------------*/
3598 genModbits (operand * left,
3605 /* the result must be bit */
3606 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3607 l = aopGet (AOP (left), 0, FALSE, FALSE);
3611 emitcode ("div", "ab");
3612 emitcode ("mov", "a,b");
3613 emitcode ("rrc", "a");
3614 aopPut (AOP (result), "c", 0);
3617 /*-----------------------------------------------------------------*/
3618 /* genModOneByte : 8 bit modulus */
3619 /*-----------------------------------------------------------------*/
3621 genModOneByte (operand * left,
3625 sym_link *opetype = operandType (result);
3629 /* signed or unsigned */
3630 if (SPEC_USIGN (opetype))
3632 /* unsigned is easy */
3633 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3634 l = aopGet (AOP (left), 0, FALSE, FALSE);
3636 emitcode ("div", "ab");
3637 aopPut (AOP (result), "b", 0);
3641 /* signed is a little bit more difficult */
3643 /* save the signs of the operands */
3644 l = aopGet (AOP (left), 0, FALSE, FALSE);
3647 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3648 emitcode ("push", "acc"); /* save it on the stack */
3650 /* now sign adjust for both left & right */
3651 l = aopGet (AOP (right), 0, FALSE, FALSE);
3654 lbl = newiTempLabel (NULL);
3655 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3656 emitcode ("cpl", "a");
3657 emitcode ("inc", "a");
3658 emitcode ("", "%05d$:", (lbl->key + 100));
3659 emitcode ("mov", "b,a");
3661 /* sign adjust left side */
3662 l = aopGet (AOP (left), 0, FALSE, FALSE);
3665 lbl = newiTempLabel (NULL);
3666 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3667 emitcode ("cpl", "a");
3668 emitcode ("inc", "a");
3669 emitcode ("", "%05d$:", (lbl->key + 100));
3671 /* now the multiplication */
3672 emitcode ("div", "ab");
3673 /* we are interested in the lower order
3675 lbl = newiTempLabel (NULL);
3676 emitcode ("pop", "acc");
3677 /* if there was an over flow we don't
3678 adjust the sign of the result */
3679 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3680 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3682 emitcode ("clr", "a");
3683 emitcode ("subb", "a,b");
3684 emitcode ("mov", "b,a");
3685 emitcode ("", "%05d$:", (lbl->key + 100));
3687 /* now we are done */
3688 aopPut (AOP (result), "b", 0);
3692 /*-----------------------------------------------------------------*/
3693 /* genMod - generates code for division */
3694 /*-----------------------------------------------------------------*/
3698 operand *left = IC_LEFT (ic);
3699 operand *right = IC_RIGHT (ic);
3700 operand *result = IC_RESULT (ic);
3702 /* assign the amsops */
3703 aopOp (left, ic, FALSE);
3704 aopOp (right, ic, FALSE);
3705 aopOp (result, ic, TRUE);
3707 /* special cases first */
3709 if (AOP_TYPE (left) == AOP_CRY &&
3710 AOP_TYPE (right) == AOP_CRY)
3712 genModbits (left, right, result);
3716 /* if both are of size == 1 */
3717 if (AOP_SIZE (left) == 1 &&
3718 AOP_SIZE (right) == 1)
3720 genModOneByte (left, right, result);
3724 /* should have been converted to function call */
3728 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (result, NULL, ic, TRUE);
3733 /*-----------------------------------------------------------------*/
3734 /* genIfxJump :- will create a jump depending on the ifx */
3735 /*-----------------------------------------------------------------*/
3737 genIfxJump (iCode * ic, char *jval)
3740 symbol *tlbl = newiTempLabel (NULL);
3743 /* if true label then we jump if condition
3747 jlbl = IC_TRUE (ic);
3748 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3749 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3753 /* false label is present */
3754 jlbl = IC_FALSE (ic);
3755 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3756 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3758 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3759 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3761 emitcode (inst, "%05d$", tlbl->key + 100);
3762 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3763 emitcode ("", "%05d$:", tlbl->key + 100);
3765 /* mark the icode as generated */
3769 /*-----------------------------------------------------------------*/
3770 /* genCmp :- greater or less than comparison */
3771 /*-----------------------------------------------------------------*/
3773 genCmp (operand * left, operand * right,
3774 operand * result, iCode * ifx, int sign, iCode *ic)
3776 int size, offset = 0;
3777 unsigned long lit = 0L;
3779 /* if left & right are bit variables */
3780 if (AOP_TYPE (left) == AOP_CRY &&
3781 AOP_TYPE (right) == AOP_CRY)
3783 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3784 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3788 /* subtract right from left if at the
3789 end the carry flag is set then we know that
3790 left is greater than right */
3791 size = max (AOP_SIZE (left), AOP_SIZE (right));
3793 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3794 if ((size == 1) && !sign &&
3795 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3797 symbol *lbl = newiTempLabel (NULL);
3798 emitcode ("cjne", "%s,%s,%05d$",
3799 aopGet (AOP (left), offset, FALSE, FALSE),
3800 aopGet (AOP (right), offset, FALSE, FALSE),
3802 emitcode ("", "%05d$:", lbl->key + 100);
3806 if (AOP_TYPE (right) == AOP_LIT)
3808 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3809 /* optimize if(x < 0) or if(x >= 0) */
3818 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3819 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3821 genIfxJump (ifx, "acc.7");
3825 emitcode ("rlc", "a");
3833 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3834 if (sign && size == 0)
3836 emitcode ("xrl", "a,#0x80");
3837 if (AOP_TYPE (right) == AOP_LIT)
3839 unsigned long lit = (unsigned long)
3840 floatFromVal (AOP (right)->aopu.aop_lit);
3841 emitcode ("subb", "a,#0x%02x",
3842 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3846 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3847 emitcode ("xrl", "b,#0x80");
3848 emitcode ("subb", "a,b");
3852 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3858 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3859 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3860 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3866 /* if the result is used in the next
3867 ifx conditional branch then generate
3868 code a little differently */
3870 genIfxJump (ifx, "c");
3873 /* leave the result in acc */
3877 /*-----------------------------------------------------------------*/
3878 /* genCmpGt :- greater than comparison */
3879 /*-----------------------------------------------------------------*/
3881 genCmpGt (iCode * ic, iCode * ifx)
3883 operand *left, *right, *result;
3884 sym_link *letype, *retype;
3887 left = IC_LEFT (ic);
3888 right = IC_RIGHT (ic);
3889 result = IC_RESULT (ic);
3891 letype = getSpec (operandType (left));
3892 retype = getSpec (operandType (right));
3893 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3894 /* assign the amsops */
3895 aopOp (left, ic, FALSE);
3896 aopOp (right, ic, FALSE);
3897 aopOp (result, ic, TRUE);
3899 genCmp (right, left, result, ifx, sign,ic);
3901 freeAsmop (result, NULL, ic, TRUE);
3904 /*-----------------------------------------------------------------*/
3905 /* genCmpLt - less than comparisons */
3906 /*-----------------------------------------------------------------*/
3908 genCmpLt (iCode * ic, iCode * ifx)
3910 operand *left, *right, *result;
3911 sym_link *letype, *retype;
3914 left = IC_LEFT (ic);
3915 right = IC_RIGHT (ic);
3916 result = IC_RESULT (ic);
3918 letype = getSpec (operandType (left));
3919 retype = getSpec (operandType (right));
3920 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3922 /* assign the amsops */
3923 aopOp (left, ic, FALSE);
3924 aopOp (right, ic, FALSE);
3925 aopOp (result, ic, TRUE);
3927 genCmp (left, right, result, ifx, sign,ic);
3929 freeAsmop (result, NULL, ic, TRUE);
3932 /*-----------------------------------------------------------------*/
3933 /* gencjneshort - compare and jump if not equal */
3934 /*-----------------------------------------------------------------*/
3936 gencjneshort (operand * left, operand * right, symbol * lbl)
3938 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3940 unsigned long lit = 0L;
3942 /* if the left side is a literal or
3943 if the right is in a pointer register and left
3945 if ((AOP_TYPE (left) == AOP_LIT) ||
3946 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3952 if (AOP_TYPE (right) == AOP_LIT)
3953 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3955 /* if the right side is a literal then anything goes */
3956 if (AOP_TYPE (right) == AOP_LIT &&
3957 AOP_TYPE (left) != AOP_DIR)
3961 emitcode ("cjne", "%s,%s,%05d$",
3962 aopGet (AOP (left), offset, FALSE, FALSE),
3963 aopGet (AOP (right), offset, FALSE, FALSE),
3969 /* if the right side is in a register or in direct space or
3970 if the left is a pointer register & right is not */
3971 else if (AOP_TYPE (right) == AOP_REG ||
3972 AOP_TYPE (right) == AOP_DIR ||
3973 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3974 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3978 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3979 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3980 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3981 emitcode ("jnz", "%05d$", lbl->key + 100);
3983 emitcode ("cjne", "a,%s,%05d$",
3984 aopGet (AOP (right), offset, FALSE, TRUE),
3991 /* right is a pointer reg need both a & b */
3994 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3995 if (strcmp (l, "b"))
3996 emitcode ("mov", "b,%s", l);
3997 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3998 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4004 /*-----------------------------------------------------------------*/
4005 /* gencjne - compare and jump if not equal */
4006 /*-----------------------------------------------------------------*/
4008 gencjne (operand * left, operand * right, symbol * lbl)
4010 symbol *tlbl = newiTempLabel (NULL);
4012 gencjneshort (left, right, lbl);
4014 emitcode ("mov", "a,%s", one);
4015 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4016 emitcode ("", "%05d$:", lbl->key + 100);
4017 emitcode ("clr", "a");
4018 emitcode ("", "%05d$:", tlbl->key + 100);
4021 /*-----------------------------------------------------------------*/
4022 /* genCmpEq - generates code for equal to */
4023 /*-----------------------------------------------------------------*/
4025 genCmpEq (iCode * ic, iCode * ifx)
4027 operand *left, *right, *result;
4029 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4030 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4031 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4033 /* if literal, literal on the right or
4034 if the right is in a pointer register and left
4036 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4037 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4039 operand *t = IC_RIGHT (ic);
4040 IC_RIGHT (ic) = IC_LEFT (ic);
4044 if (ifx && !AOP_SIZE (result))
4047 /* if they are both bit variables */
4048 if (AOP_TYPE (left) == AOP_CRY &&
4049 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4051 if (AOP_TYPE (right) == AOP_LIT)
4053 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4057 emitcode ("cpl", "c");
4061 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4065 emitcode ("clr", "c");
4067 /* AOP_TYPE(right) == AOP_CRY */
4071 symbol *lbl = newiTempLabel (NULL);
4072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4073 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4074 emitcode ("cpl", "c");
4075 emitcode ("", "%05d$:", (lbl->key + 100));
4077 /* if true label then we jump if condition
4079 tlbl = newiTempLabel (NULL);
4082 emitcode ("jnc", "%05d$", tlbl->key + 100);
4083 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4087 emitcode ("jc", "%05d$", tlbl->key + 100);
4088 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4090 emitcode ("", "%05d$:", tlbl->key + 100);
4094 tlbl = newiTempLabel (NULL);
4095 gencjneshort (left, right, tlbl);
4098 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4099 emitcode ("", "%05d$:", tlbl->key + 100);
4103 symbol *lbl = newiTempLabel (NULL);
4104 emitcode ("sjmp", "%05d$", lbl->key + 100);
4105 emitcode ("", "%05d$:", tlbl->key + 100);
4106 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4107 emitcode ("", "%05d$:", lbl->key + 100);
4110 /* mark the icode as generated */
4115 /* if they are both bit variables */
4116 if (AOP_TYPE (left) == AOP_CRY &&
4117 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4119 if (AOP_TYPE (right) == AOP_LIT)
4121 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4125 emitcode ("cpl", "c");
4129 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4133 emitcode ("clr", "c");
4135 /* AOP_TYPE(right) == AOP_CRY */
4139 symbol *lbl = newiTempLabel (NULL);
4140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4141 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4142 emitcode ("cpl", "c");
4143 emitcode ("", "%05d$:", (lbl->key + 100));
4146 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4153 genIfxJump (ifx, "c");
4156 /* if the result is used in an arithmetic operation
4157 then put the result in place */
4162 gencjne (left, right, newiTempLabel (NULL));
4163 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4165 aopPut (AOP (result), "a", 0);
4170 genIfxJump (ifx, "a");
4173 /* if the result is used in an arithmetic operation
4174 then put the result in place */
4175 if (AOP_TYPE (result) != AOP_CRY)
4177 /* leave the result in acc */
4181 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4182 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4183 freeAsmop (result, NULL, ic, TRUE);
4186 /*-----------------------------------------------------------------*/
4187 /* ifxForOp - returns the icode containing the ifx for operand */
4188 /*-----------------------------------------------------------------*/
4190 ifxForOp (operand * op, iCode * ic)
4192 /* if true symbol then needs to be assigned */
4193 if (IS_TRUE_SYMOP (op))
4196 /* if this has register type condition and
4197 the next instruction is ifx with the same operand
4198 and live to of the operand is upto the ifx only then */
4200 ic->next->op == IFX &&
4201 IC_COND (ic->next)->key == op->key &&
4202 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4208 /*-----------------------------------------------------------------*/
4209 /* hasInc - operand is incremented before any other use */
4210 /*-----------------------------------------------------------------*/
4212 hasInc (operand *op, iCode *ic)
4214 sym_link *type = operandType(op);
4215 sym_link *retype = getSpec (type);
4216 iCode *lic = ic->next;
4219 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4220 if (!IS_SYMOP(op)) return NULL;
4222 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4223 isize = getSize(type->next);
4225 /* if operand of the form op = op + <sizeof *op> */
4226 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4227 isOperandEqual(IC_RESULT(lic),op) &&
4228 isOperandLiteral(IC_RIGHT(lic)) &&
4229 operandLitValue(IC_RIGHT(lic)) == isize) {
4232 /* if the operand used or deffed */
4233 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4241 /*-----------------------------------------------------------------*/
4242 /* genAndOp - for && operation */
4243 /*-----------------------------------------------------------------*/
4245 genAndOp (iCode * ic)
4247 operand *left, *right, *result;
4250 /* note here that && operations that are in an
4251 if statement are taken away by backPatchLabels
4252 only those used in arthmetic operations remain */
4253 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4254 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4255 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4257 /* if both are bit variables */
4258 if (AOP_TYPE (left) == AOP_CRY &&
4259 AOP_TYPE (right) == AOP_CRY)
4261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4262 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4267 tlbl = newiTempLabel (NULL);
4269 emitcode ("jz", "%05d$", tlbl->key + 100);
4271 emitcode ("", "%05d$:", tlbl->key + 100);
4275 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4276 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4277 freeAsmop (result, NULL, ic, TRUE);
4281 /*-----------------------------------------------------------------*/
4282 /* genOrOp - for || operation */
4283 /*-----------------------------------------------------------------*/
4285 genOrOp (iCode * ic)
4287 operand *left, *right, *result;
4290 /* note here that || operations that are in an
4291 if statement are taken away by backPatchLabels
4292 only those used in arthmetic operations remain */
4293 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4294 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4295 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4297 /* if both are bit variables */
4298 if (AOP_TYPE (left) == AOP_CRY &&
4299 AOP_TYPE (right) == AOP_CRY)
4301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4302 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4307 tlbl = newiTempLabel (NULL);
4309 emitcode ("jnz", "%05d$", tlbl->key + 100);
4311 emitcode ("", "%05d$:", tlbl->key + 100);
4315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4317 freeAsmop (result, NULL, ic, TRUE);
4320 /*-----------------------------------------------------------------*/
4321 /* isLiteralBit - test if lit == 2^n */
4322 /*-----------------------------------------------------------------*/
4324 isLiteralBit (unsigned long lit)
4326 unsigned long pw[32] =
4327 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4328 0x100L, 0x200L, 0x400L, 0x800L,
4329 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4330 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4331 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4332 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4333 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4336 for (idx = 0; idx < 32; idx++)
4342 /*-----------------------------------------------------------------*/
4343 /* continueIfTrue - */
4344 /*-----------------------------------------------------------------*/
4346 continueIfTrue (iCode * ic)
4349 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4353 /*-----------------------------------------------------------------*/
4355 /*-----------------------------------------------------------------*/
4357 jumpIfTrue (iCode * ic)
4360 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4364 /*-----------------------------------------------------------------*/
4365 /* jmpTrueOrFalse - */
4366 /*-----------------------------------------------------------------*/
4368 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4370 // ugly but optimized by peephole
4373 symbol *nlbl = newiTempLabel (NULL);
4374 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4375 emitcode ("", "%05d$:", tlbl->key + 100);
4376 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4377 emitcode ("", "%05d$:", nlbl->key + 100);
4381 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4382 emitcode ("", "%05d$:", tlbl->key + 100);
4387 /*-----------------------------------------------------------------*/
4388 /* genAnd - code for and */
4389 /*-----------------------------------------------------------------*/
4391 genAnd (iCode * ic, iCode * ifx)
4393 operand *left, *right, *result;
4394 int size, offset = 0;
4395 unsigned long lit = 0L;
4399 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4400 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4401 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4404 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4406 AOP_TYPE (left), AOP_TYPE (right));
4407 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4409 AOP_SIZE (left), AOP_SIZE (right));
4412 /* if left is a literal & right is not then exchange them */
4413 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4414 AOP_NEEDSACC (left))
4416 operand *tmp = right;
4421 /* if result = right then exchange them */
4422 if (sameRegs (AOP (result), AOP (right)))
4424 operand *tmp = right;
4429 /* if right is bit then exchange them */
4430 if (AOP_TYPE (right) == AOP_CRY &&
4431 AOP_TYPE (left) != AOP_CRY)
4433 operand *tmp = right;
4437 if (AOP_TYPE (right) == AOP_LIT)
4438 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4440 size = AOP_SIZE (result);
4443 // result = bit & yy;
4444 if (AOP_TYPE (left) == AOP_CRY)
4446 // c = bit & literal;
4447 if (AOP_TYPE (right) == AOP_LIT)
4451 if (size && sameRegs (AOP (result), AOP (left)))
4454 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4459 if (size && (AOP_TYPE (result) == AOP_CRY))
4461 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4464 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4469 emitcode ("clr", "c");
4474 if (AOP_TYPE (right) == AOP_CRY)
4477 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4478 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4483 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4485 emitcode ("rrc", "a");
4486 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4494 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4495 genIfxJump (ifx, "c");
4499 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4500 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4501 if ((AOP_TYPE (right) == AOP_LIT) &&
4502 (AOP_TYPE (result) == AOP_CRY) &&
4503 (AOP_TYPE (left) != AOP_CRY))
4505 int posbit = isLiteralBit (lit);
4510 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4513 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4519 sprintf (buffer, "acc.%d", posbit & 0x07);
4520 genIfxJump (ifx, buffer);
4527 symbol *tlbl = newiTempLabel (NULL);
4528 int sizel = AOP_SIZE (left);
4530 emitcode ("setb", "c");
4533 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4535 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4537 if ((posbit = isLiteralBit (bytelit)) != 0)
4538 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4541 if (bytelit != 0x0FFL)
4542 emitcode ("anl", "a,%s",
4543 aopGet (AOP (right), offset, FALSE, TRUE));
4544 emitcode ("jnz", "%05d$", tlbl->key + 100);
4549 // bit = left & literal
4552 emitcode ("clr", "c");
4553 emitcode ("", "%05d$:", tlbl->key + 100);
4555 // if(left & literal)
4559 jmpTrueOrFalse (ifx, tlbl);
4567 /* if left is same as result */
4568 if (sameRegs (AOP (result), AOP (left)))
4570 for (; size--; offset++)
4572 if (AOP_TYPE (right) == AOP_LIT)
4574 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4576 else if (bytelit == 0)
4577 aopPut (AOP (result), zero, offset);
4578 else if (IS_AOP_PREG (result))
4580 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4581 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4582 aopPut (AOP (result), "a", offset);
4585 emitcode ("anl", "%s,%s",
4586 aopGet (AOP (left), offset, FALSE, TRUE),
4587 aopGet (AOP (right), offset, FALSE, FALSE));
4591 if (AOP_TYPE (left) == AOP_ACC)
4592 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4595 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4596 if (IS_AOP_PREG (result))
4598 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4599 aopPut (AOP (result), "a", offset);
4603 emitcode ("anl", "%s,a",
4604 aopGet (AOP (left), offset, FALSE, TRUE));
4611 // left & result in different registers
4612 if (AOP_TYPE (result) == AOP_CRY)
4615 // if(size), result in bit
4616 // if(!size && ifx), conditional oper: if(left & right)
4617 symbol *tlbl = newiTempLabel (NULL);
4618 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4620 emitcode ("setb", "c");
4623 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4624 emitcode ("anl", "a,%s",
4625 aopGet (AOP (right), offset, FALSE, FALSE));
4627 if (AOP_TYPE(left)==AOP_ACC) {
4628 emitcode("mov", "b,a");
4629 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4630 emitcode("anl", "a,b");
4632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4633 emitcode ("anl", "a,%s",
4634 aopGet (AOP (left), offset, FALSE, FALSE));
4637 emitcode ("jnz", "%05d$", tlbl->key + 100);
4643 emitcode ("", "%05d$:", tlbl->key + 100);
4647 jmpTrueOrFalse (ifx, tlbl);
4651 for (; (size--); offset++)
4654 // result = left & right
4655 if (AOP_TYPE (right) == AOP_LIT)
4657 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4659 aopPut (AOP (result),
4660 aopGet (AOP (left), offset, FALSE, FALSE),
4664 else if (bytelit == 0)
4666 aopPut (AOP (result), zero, offset);
4670 // faster than result <- left, anl result,right
4671 // and better if result is SFR
4672 if (AOP_TYPE (left) == AOP_ACC)
4673 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4676 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4677 emitcode ("anl", "a,%s",
4678 aopGet (AOP (left), offset, FALSE, FALSE));
4680 aopPut (AOP (result), "a", offset);
4686 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688 freeAsmop (result, NULL, ic, TRUE);
4691 /*-----------------------------------------------------------------*/
4692 /* genOr - code for or */
4693 /*-----------------------------------------------------------------*/
4695 genOr (iCode * ic, iCode * ifx)
4697 operand *left, *right, *result;
4698 int size, offset = 0;
4699 unsigned long lit = 0L;
4701 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4702 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4703 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4706 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4708 AOP_TYPE (left), AOP_TYPE (right));
4709 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4711 AOP_SIZE (left), AOP_SIZE (right));
4714 /* if left is a literal & right is not then exchange them */
4715 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4716 AOP_NEEDSACC (left))
4718 operand *tmp = right;
4723 /* if result = right then exchange them */
4724 if (sameRegs (AOP (result), AOP (right)))
4726 operand *tmp = right;
4731 /* if right is bit then exchange them */
4732 if (AOP_TYPE (right) == AOP_CRY &&
4733 AOP_TYPE (left) != AOP_CRY)
4735 operand *tmp = right;
4739 if (AOP_TYPE (right) == AOP_LIT)
4740 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4742 size = AOP_SIZE (result);
4746 if (AOP_TYPE (left) == AOP_CRY)
4748 if (AOP_TYPE (right) == AOP_LIT)
4750 // c = bit & literal;
4753 // lit != 0 => result = 1
4754 if (AOP_TYPE (result) == AOP_CRY)
4757 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4759 continueIfTrue (ifx);
4762 emitcode ("setb", "c");
4766 // lit == 0 => result = left
4767 if (size && sameRegs (AOP (result), AOP (left)))
4769 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4774 if (AOP_TYPE (right) == AOP_CRY)
4777 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4778 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4783 symbol *tlbl = newiTempLabel (NULL);
4784 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4785 emitcode ("setb", "c");
4786 emitcode ("jb", "%s,%05d$",
4787 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4789 emitcode ("jnz", "%05d$", tlbl->key + 100);
4790 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4792 jmpTrueOrFalse (ifx, tlbl);
4798 emitcode ("", "%05d$:", tlbl->key + 100);
4807 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4808 genIfxJump (ifx, "c");
4812 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4813 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4814 if ((AOP_TYPE (right) == AOP_LIT) &&
4815 (AOP_TYPE (result) == AOP_CRY) &&
4816 (AOP_TYPE (left) != AOP_CRY))
4822 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4824 continueIfTrue (ifx);
4829 // lit = 0, result = boolean(left)
4831 emitcode ("setb", "c");
4835 symbol *tlbl = newiTempLabel (NULL);
4836 emitcode ("jnz", "%05d$", tlbl->key + 100);
4838 emitcode ("", "%05d$:", tlbl->key + 100);
4842 genIfxJump (ifx, "a");
4850 /* if left is same as result */
4851 if (sameRegs (AOP (result), AOP (left)))
4853 for (; size--; offset++)
4855 if (AOP_TYPE (right) == AOP_LIT)
4857 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4859 else if (IS_AOP_PREG (left))
4861 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4862 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4863 aopPut (AOP (result), "a", offset);
4866 emitcode ("orl", "%s,%s",
4867 aopGet (AOP (left), offset, FALSE, TRUE),
4868 aopGet (AOP (right), offset, FALSE, FALSE));
4872 if (AOP_TYPE (left) == AOP_ACC)
4873 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4876 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4877 if (IS_AOP_PREG (left))
4879 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4880 aopPut (AOP (result), "a", offset);
4883 emitcode ("orl", "%s,a",
4884 aopGet (AOP (left), offset, FALSE, TRUE));
4891 // left & result in different registers
4892 if (AOP_TYPE (result) == AOP_CRY)
4895 // if(size), result in bit
4896 // if(!size && ifx), conditional oper: if(left | right)
4897 symbol *tlbl = newiTempLabel (NULL);
4898 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4900 emitcode ("setb", "c");
4903 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4904 emitcode ("orl", "a,%s",
4905 aopGet (AOP (right), offset, FALSE, FALSE));
4907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4908 emitcode ("orl", "a,%s",
4909 aopGet (AOP (left), offset, FALSE, FALSE));
4911 emitcode ("jnz", "%05d$", tlbl->key + 100);
4917 emitcode ("", "%05d$:", tlbl->key + 100);
4921 jmpTrueOrFalse (ifx, tlbl);
4924 for (; (size--); offset++)
4927 // result = left & right
4928 if (AOP_TYPE (right) == AOP_LIT)
4930 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4932 aopPut (AOP (result),
4933 aopGet (AOP (left), offset, FALSE, FALSE),
4938 // faster than result <- left, anl result,right
4939 // and better if result is SFR
4940 if (AOP_TYPE (left) == AOP_ACC)
4941 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4944 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4945 emitcode ("orl", "a,%s",
4946 aopGet (AOP (left), offset, FALSE, FALSE));
4948 aopPut (AOP (result), "a", offset);
4953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4955 freeAsmop (result, NULL, ic, TRUE);
4958 /*-----------------------------------------------------------------*/
4959 /* genXor - code for xclusive or */
4960 /*-----------------------------------------------------------------*/
4962 genXor (iCode * ic, iCode * ifx)
4964 operand *left, *right, *result;
4965 int size, offset = 0;
4966 unsigned long lit = 0L;
4968 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4969 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4970 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4973 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4975 AOP_TYPE (left), AOP_TYPE (right));
4976 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4978 AOP_SIZE (left), AOP_SIZE (right));
4981 /* if left is a literal & right is not ||
4982 if left needs acc & right does not */
4983 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4984 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4986 operand *tmp = right;
4991 /* if result = right then exchange them */
4992 if (sameRegs (AOP (result), AOP (right)))
4994 operand *tmp = right;
4999 /* if right is bit then exchange them */
5000 if (AOP_TYPE (right) == AOP_CRY &&
5001 AOP_TYPE (left) != AOP_CRY)
5003 operand *tmp = right;
5007 if (AOP_TYPE (right) == AOP_LIT)
5008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5010 size = AOP_SIZE (result);
5014 if (AOP_TYPE (left) == AOP_CRY)
5016 if (AOP_TYPE (right) == AOP_LIT)
5018 // c = bit & literal;
5021 // lit>>1 != 0 => result = 1
5022 if (AOP_TYPE (result) == AOP_CRY)
5025 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5027 continueIfTrue (ifx);
5030 emitcode ("setb", "c");
5037 // lit == 0, result = left
5038 if (size && sameRegs (AOP (result), AOP (left)))
5040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5044 // lit == 1, result = not(left)
5045 if (size && sameRegs (AOP (result), AOP (left)))
5047 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5053 emitcode ("cpl", "c");
5062 symbol *tlbl = newiTempLabel (NULL);
5063 if (AOP_TYPE (right) == AOP_CRY)
5066 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5070 int sizer = AOP_SIZE (right);
5072 // if val>>1 != 0, result = 1
5073 emitcode ("setb", "c");
5076 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5078 // test the msb of the lsb
5079 emitcode ("anl", "a,#0xfe");
5080 emitcode ("jnz", "%05d$", tlbl->key + 100);
5084 emitcode ("rrc", "a");
5086 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5087 emitcode ("cpl", "c");
5088 emitcode ("", "%05d$:", (tlbl->key + 100));
5095 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5096 genIfxJump (ifx, "c");
5100 if (sameRegs (AOP (result), AOP (left)))
5102 /* if left is same as result */
5103 for (; size--; offset++)
5105 if (AOP_TYPE (right) == AOP_LIT)
5107 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5109 else if (IS_AOP_PREG (left))
5111 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5112 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5113 aopPut (AOP (result), "a", offset);
5116 emitcode ("xrl", "%s,%s",
5117 aopGet (AOP (left), offset, FALSE, TRUE),
5118 aopGet (AOP (right), offset, FALSE, FALSE));
5122 if (AOP_TYPE (left) == AOP_ACC)
5123 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5126 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5127 if (IS_AOP_PREG (left))
5129 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5130 aopPut (AOP (result), "a", offset);
5133 emitcode ("xrl", "%s,a",
5134 aopGet (AOP (left), offset, FALSE, TRUE));
5141 // left & result in different registers
5142 if (AOP_TYPE (result) == AOP_CRY)
5145 // if(size), result in bit
5146 // if(!size && ifx), conditional oper: if(left ^ right)
5147 symbol *tlbl = newiTempLabel (NULL);
5148 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5150 emitcode ("setb", "c");
5153 if ((AOP_TYPE (right) == AOP_LIT) &&
5154 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5156 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5160 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5161 emitcode ("xrl", "a,%s",
5162 aopGet (AOP (right), offset, FALSE, FALSE));
5164 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5165 emitcode ("xrl", "a,%s",
5166 aopGet (AOP (left), offset, FALSE, FALSE));
5169 emitcode ("jnz", "%05d$", tlbl->key + 100);
5175 emitcode ("", "%05d$:", tlbl->key + 100);
5179 jmpTrueOrFalse (ifx, tlbl);
5182 for (; (size--); offset++)
5185 // result = left & right
5186 if (AOP_TYPE (right) == AOP_LIT)
5188 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5190 aopPut (AOP (result),
5191 aopGet (AOP (left), offset, FALSE, FALSE),
5196 // faster than result <- left, anl result,right
5197 // and better if result is SFR
5198 if (AOP_TYPE (left) == AOP_ACC)
5199 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5202 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5203 emitcode ("xrl", "a,%s",
5204 aopGet (AOP (left), offset, FALSE, TRUE));
5206 aopPut (AOP (result), "a", offset);
5211 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5212 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5213 freeAsmop (result, NULL, ic, TRUE);
5216 /*-----------------------------------------------------------------*/
5217 /* genInline - write the inline code out */
5218 /*-----------------------------------------------------------------*/
5220 genInline (iCode * ic)
5222 char *buffer, *bp, *bp1;
5224 _G.inLine += (!options.asmpeep);
5226 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5227 strcpy (buffer, IC_INLINE (ic));
5229 /* emit each line as a code */
5254 /* emitcode("",buffer); */
5255 _G.inLine -= (!options.asmpeep);
5258 /*-----------------------------------------------------------------*/
5259 /* genRRC - rotate right with carry */
5260 /*-----------------------------------------------------------------*/
5264 operand *left, *result;
5265 int size, offset = 0;
5268 /* rotate right with carry */
5269 left = IC_LEFT (ic);
5270 result = IC_RESULT (ic);
5271 aopOp (left, ic, FALSE);
5272 aopOp (result, ic, FALSE);
5274 /* move it to the result */
5275 size = AOP_SIZE (result);
5277 if (size == 1) { /* special case for 1 byte */
5278 l = aopGet (AOP (left), offset, FALSE, FALSE);
5280 emitcode ("rr", "a");
5286 l = aopGet (AOP (left), offset, FALSE, FALSE);
5288 emitcode ("rrc", "a");
5289 if (AOP_SIZE (result) > 1)
5290 aopPut (AOP (result), "a", offset--);
5292 /* now we need to put the carry into the
5293 highest order byte of the result */
5294 if (AOP_SIZE (result) > 1)
5296 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5299 emitcode ("mov", "acc.7,c");
5301 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5302 freeAsmop (left, NULL, ic, TRUE);
5303 freeAsmop (result, NULL, ic, TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* genRLC - generate code for rotate left with carry */
5308 /*-----------------------------------------------------------------*/
5312 operand *left, *result;
5313 int size, offset = 0;
5316 /* rotate right with carry */
5317 left = IC_LEFT (ic);
5318 result = IC_RESULT (ic);
5319 aopOp (left, ic, FALSE);
5320 aopOp (result, ic, FALSE);
5322 /* move it to the result */
5323 size = AOP_SIZE (result);
5327 l = aopGet (AOP (left), offset, FALSE, FALSE);
5329 if (size == 0) { /* special case for 1 byte */
5333 emitcode ("add", "a,acc");
5334 if (AOP_SIZE (result) > 1)
5335 aopPut (AOP (result), "a", offset++);
5338 l = aopGet (AOP (left), offset, FALSE, FALSE);
5340 emitcode ("rlc", "a");
5341 if (AOP_SIZE (result) > 1)
5342 aopPut (AOP (result), "a", offset++);
5345 /* now we need to put the carry into the
5346 highest order byte of the result */
5347 if (AOP_SIZE (result) > 1)
5349 l = aopGet (AOP (result), 0, FALSE, FALSE);
5352 emitcode ("mov", "acc.0,c");
5354 aopPut (AOP (result), "a", 0);
5355 freeAsmop (left, NULL, ic, TRUE);
5356 freeAsmop (result, NULL, ic, TRUE);
5359 /*-----------------------------------------------------------------*/
5360 /* genGetHbit - generates code get highest order bit */
5361 /*-----------------------------------------------------------------*/
5363 genGetHbit (iCode * ic)
5365 operand *left, *result;
5366 left = IC_LEFT (ic);
5367 result = IC_RESULT (ic);
5368 aopOp (left, ic, FALSE);
5369 aopOp (result, ic, FALSE);
5371 /* get the highest order byte into a */
5372 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5373 if (AOP_TYPE (result) == AOP_CRY)
5375 emitcode ("rlc", "a");
5380 emitcode ("rl", "a");
5381 emitcode ("anl", "a,#0x01");
5386 freeAsmop (left, NULL, ic, TRUE);
5387 freeAsmop (result, NULL, ic, TRUE);
5390 /*-----------------------------------------------------------------*/
5391 /* AccRol - rotate left accumulator by known count */
5392 /*-----------------------------------------------------------------*/
5394 AccRol (int shCount)
5396 shCount &= 0x0007; // shCount : 0..7
5403 emitcode ("rl", "a");
5406 emitcode ("rl", "a");
5407 emitcode ("rl", "a");
5410 emitcode ("swap", "a");
5411 emitcode ("rr", "a");
5414 emitcode ("swap", "a");
5417 emitcode ("swap", "a");
5418 emitcode ("rl", "a");
5421 emitcode ("rr", "a");
5422 emitcode ("rr", "a");
5425 emitcode ("rr", "a");
5430 /*-----------------------------------------------------------------*/
5431 /* AccLsh - left shift accumulator by known count */
5432 /*-----------------------------------------------------------------*/
5434 AccLsh (int shCount)
5439 emitcode ("add", "a,acc");
5440 else if (shCount == 2)
5442 emitcode ("add", "a,acc");
5443 emitcode ("add", "a,acc");
5447 /* rotate left accumulator */
5449 /* and kill the lower order bits */
5450 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5455 /*-----------------------------------------------------------------*/
5456 /* AccRsh - right shift accumulator by known count */
5457 /*-----------------------------------------------------------------*/
5459 AccRsh (int shCount)
5466 emitcode ("rrc", "a");
5470 /* rotate right accumulator */
5471 AccRol (8 - shCount);
5472 /* and kill the higher order bits */
5473 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5478 /*-----------------------------------------------------------------*/
5479 /* AccSRsh - signed right shift accumulator by known count */
5480 /*-----------------------------------------------------------------*/
5482 AccSRsh (int shCount)
5489 emitcode ("mov", "c,acc.7");
5490 emitcode ("rrc", "a");
5492 else if (shCount == 2)
5494 emitcode ("mov", "c,acc.7");
5495 emitcode ("rrc", "a");
5496 emitcode ("mov", "c,acc.7");
5497 emitcode ("rrc", "a");
5501 tlbl = newiTempLabel (NULL);
5502 /* rotate right accumulator */
5503 AccRol (8 - shCount);
5504 /* and kill the higher order bits */
5505 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5506 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5507 emitcode ("orl", "a,#0x%02x",
5508 (unsigned char) ~SRMask[shCount]);
5509 emitcode ("", "%05d$:", tlbl->key + 100);
5514 /*-----------------------------------------------------------------*/
5515 /* shiftR1Left2Result - shift right one byte from left to result */
5516 /*-----------------------------------------------------------------*/
5518 shiftR1Left2Result (operand * left, int offl,
5519 operand * result, int offr,
5520 int shCount, int sign)
5522 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5523 /* shift right accumulator */
5528 aopPut (AOP (result), "a", offr);
5531 /*-----------------------------------------------------------------*/
5532 /* shiftL1Left2Result - shift left one byte from left to result */
5533 /*-----------------------------------------------------------------*/
5535 shiftL1Left2Result (operand * left, int offl,
5536 operand * result, int offr, int shCount)
5539 l = aopGet (AOP (left), offl, FALSE, FALSE);
5541 /* shift left accumulator */
5543 aopPut (AOP (result), "a", offr);
5546 /*-----------------------------------------------------------------*/
5547 /* movLeft2Result - move byte from left to result */
5548 /*-----------------------------------------------------------------*/
5550 movLeft2Result (operand * left, int offl,
5551 operand * result, int offr, int sign)
5554 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5556 l = aopGet (AOP (left), offl, FALSE, FALSE);
5558 if (*l == '@' && (IS_AOP_PREG (result)))
5560 emitcode ("mov", "a,%s", l);
5561 aopPut (AOP (result), "a", offr);
5566 aopPut (AOP (result), l, offr);
5569 /* MSB sign in acc.7 ! */
5570 if (getDataSize (left) == offl + 1)
5572 emitcode ("mov", "a,%s", l);
5573 aopPut (AOP (result), "a", offr);
5580 /*-----------------------------------------------------------------*/
5581 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5582 /*-----------------------------------------------------------------*/
5586 emitcode ("rrc", "a");
5587 emitcode ("xch", "a,%s", x);
5588 emitcode ("rrc", "a");
5589 emitcode ("xch", "a,%s", x);
5592 /*-----------------------------------------------------------------*/
5593 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5594 /*-----------------------------------------------------------------*/
5598 emitcode ("xch", "a,%s", x);
5599 emitcode ("rlc", "a");
5600 emitcode ("xch", "a,%s", x);
5601 emitcode ("rlc", "a");
5604 /*-----------------------------------------------------------------*/
5605 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5606 /*-----------------------------------------------------------------*/
5610 emitcode ("xch", "a,%s", x);
5611 emitcode ("add", "a,acc");
5612 emitcode ("xch", "a,%s", x);
5613 emitcode ("rlc", "a");
5616 /*-----------------------------------------------------------------*/
5617 /* AccAXLsh - left shift a:x by known count (0..7) */
5618 /*-----------------------------------------------------------------*/
5620 AccAXLsh (char *x, int shCount)
5635 case 5: // AAAAABBB:CCCCCDDD
5637 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5639 emitcode ("anl", "a,#0x%02x",
5640 SLMask[shCount]); // BBB00000:CCCCCDDD
5642 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5644 AccRol (shCount); // DDDCCCCC:BBB00000
5646 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5648 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5650 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5652 emitcode ("anl", "a,#0x%02x",
5653 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5655 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5657 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5660 case 6: // AAAAAABB:CCCCCCDD
5661 emitcode ("anl", "a,#0x%02x",
5662 SRMask[shCount]); // 000000BB:CCCCCCDD
5663 emitcode ("mov", "c,acc.0"); // c = B
5664 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5666 AccAXRrl1 (x); // BCCCCCCD:D000000B
5667 AccAXRrl1 (x); // BBCCCCCC:DD000000
5669 emitcode("rrc","a");
5670 emitcode("xch","a,%s", x);
5671 emitcode("rrc","a");
5672 emitcode("mov","c,acc.0"); //<< get correct bit
5673 emitcode("xch","a,%s", x);
5675 emitcode("rrc","a");
5676 emitcode("xch","a,%s", x);
5677 emitcode("rrc","a");
5678 emitcode("xch","a,%s", x);
5681 case 7: // a:x <<= 7
5683 emitcode ("anl", "a,#0x%02x",
5684 SRMask[shCount]); // 0000000B:CCCCCCCD
5686 emitcode ("mov", "c,acc.0"); // c = B
5688 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5690 AccAXRrl1 (x); // BCCCCCCC:D0000000
5698 /*-----------------------------------------------------------------*/
5699 /* AccAXRsh - right shift a:x known count (0..7) */
5700 /*-----------------------------------------------------------------*/
5702 AccAXRsh (char *x, int shCount)
5710 AccAXRrl1 (x); // 0->a:x
5715 AccAXRrl1 (x); // 0->a:x
5718 AccAXRrl1 (x); // 0->a:x
5723 case 5: // AAAAABBB:CCCCCDDD = a:x
5725 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5727 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5729 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5731 emitcode ("anl", "a,#0x%02x",
5732 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5734 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5736 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5738 emitcode ("anl", "a,#0x%02x",
5739 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5741 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5743 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5745 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5748 case 6: // AABBBBBB:CCDDDDDD
5750 emitcode ("mov", "c,acc.7");
5751 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5753 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5755 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5757 emitcode ("anl", "a,#0x%02x",
5758 SRMask[shCount]); // 000000AA:BBBBBBCC
5761 case 7: // ABBBBBBB:CDDDDDDD
5763 emitcode ("mov", "c,acc.7"); // c = A
5765 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5767 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5769 emitcode ("anl", "a,#0x%02x",
5770 SRMask[shCount]); // 0000000A:BBBBBBBC
5778 /*-----------------------------------------------------------------*/
5779 /* AccAXRshS - right shift signed a:x known count (0..7) */
5780 /*-----------------------------------------------------------------*/
5782 AccAXRshS (char *x, int shCount)
5790 emitcode ("mov", "c,acc.7");
5791 AccAXRrl1 (x); // s->a:x
5795 emitcode ("mov", "c,acc.7");
5796 AccAXRrl1 (x); // s->a:x
5798 emitcode ("mov", "c,acc.7");
5799 AccAXRrl1 (x); // s->a:x
5804 case 5: // AAAAABBB:CCCCCDDD = a:x
5806 tlbl = newiTempLabel (NULL);
5807 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5809 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5811 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5813 emitcode ("anl", "a,#0x%02x",
5814 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5816 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5818 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5820 emitcode ("anl", "a,#0x%02x",
5821 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5823 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5825 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5827 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5829 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5830 emitcode ("orl", "a,#0x%02x",
5831 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5833 emitcode ("", "%05d$:", tlbl->key + 100);
5834 break; // SSSSAAAA:BBBCCCCC
5836 case 6: // AABBBBBB:CCDDDDDD
5838 tlbl = newiTempLabel (NULL);
5839 emitcode ("mov", "c,acc.7");
5840 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5842 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5844 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5846 emitcode ("anl", "a,#0x%02x",
5847 SRMask[shCount]); // 000000AA:BBBBBBCC
5849 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5850 emitcode ("orl", "a,#0x%02x",
5851 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5853 emitcode ("", "%05d$:", tlbl->key + 100);
5855 case 7: // ABBBBBBB:CDDDDDDD
5857 tlbl = newiTempLabel (NULL);
5858 emitcode ("mov", "c,acc.7"); // c = A
5860 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5862 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5864 emitcode ("anl", "a,#0x%02x",
5865 SRMask[shCount]); // 0000000A:BBBBBBBC
5867 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5868 emitcode ("orl", "a,#0x%02x",
5869 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5871 emitcode ("", "%05d$:", tlbl->key + 100);
5878 /*-----------------------------------------------------------------*/
5879 /* shiftL2Left2Result - shift left two bytes from left to result */
5880 /*-----------------------------------------------------------------*/
5882 shiftL2Left2Result (operand * left, int offl,
5883 operand * result, int offr, int shCount)
5885 if (sameRegs (AOP (result), AOP (left)) &&
5886 ((offl + MSB16) == offr))
5888 /* don't crash result[offr] */
5889 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5890 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5894 movLeft2Result (left, offl, result, offr, 0);
5895 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5897 /* ax << shCount (x = lsb(result)) */
5898 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5899 aopPut (AOP (result), "a", offr + MSB16);
5903 /*-----------------------------------------------------------------*/
5904 /* shiftR2Left2Result - shift right two bytes from left to result */
5905 /*-----------------------------------------------------------------*/
5907 shiftR2Left2Result (operand * left, int offl,
5908 operand * result, int offr,
5909 int shCount, int sign)
5911 if (sameRegs (AOP (result), AOP (left)) &&
5912 ((offl + MSB16) == offr))
5914 /* don't crash result[offr] */
5915 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5916 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5920 movLeft2Result (left, offl, result, offr, 0);
5921 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5923 /* a:x >> shCount (x = lsb(result)) */
5925 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5927 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5928 if (getDataSize (result) > 1)
5929 aopPut (AOP (result), "a", offr + MSB16);
5932 /*-----------------------------------------------------------------*/
5933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5934 /*-----------------------------------------------------------------*/
5936 shiftLLeftOrResult (operand * left, int offl,
5937 operand * result, int offr, int shCount)
5939 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5940 /* shift left accumulator */
5942 /* or with result */
5943 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5944 /* back to result */
5945 aopPut (AOP (result), "a", offr);
5948 /*-----------------------------------------------------------------*/
5949 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5950 /*-----------------------------------------------------------------*/
5952 shiftRLeftOrResult (operand * left, int offl,
5953 operand * result, int offr, int shCount)
5955 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5956 /* shift right accumulator */
5958 /* or with result */
5959 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5960 /* back to result */
5961 aopPut (AOP (result), "a", offr);
5964 /*-----------------------------------------------------------------*/
5965 /* genlshOne - left shift a one byte quantity by known count */
5966 /*-----------------------------------------------------------------*/
5968 genlshOne (operand * result, operand * left, int shCount)
5970 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5973 /*-----------------------------------------------------------------*/
5974 /* genlshTwo - left shift two bytes by known amount != 0 */
5975 /*-----------------------------------------------------------------*/
5977 genlshTwo (operand * result, operand * left, int shCount)
5981 size = getDataSize (result);
5983 /* if shCount >= 8 */
5991 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5993 movLeft2Result (left, LSB, result, MSB16, 0);
5995 aopPut (AOP (result), zero, LSB);
5998 /* 1 <= shCount <= 7 */
6002 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6004 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6008 /*-----------------------------------------------------------------*/
6009 /* shiftLLong - shift left one long from left to result */
6010 /* offl = LSB or MSB16 */
6011 /*-----------------------------------------------------------------*/
6013 shiftLLong (operand * left, operand * result, int offr)
6016 int size = AOP_SIZE (result);
6018 if (size >= LSB + offr)
6020 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6022 emitcode ("add", "a,acc");
6023 if (sameRegs (AOP (left), AOP (result)) &&
6024 size >= MSB16 + offr && offr != LSB)
6025 emitcode ("xch", "a,%s",
6026 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6028 aopPut (AOP (result), "a", LSB + offr);
6031 if (size >= MSB16 + offr)
6033 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6035 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6038 emitcode ("rlc", "a");
6039 if (sameRegs (AOP (left), AOP (result)) &&
6040 size >= MSB24 + offr && offr != LSB)
6041 emitcode ("xch", "a,%s",
6042 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6044 aopPut (AOP (result), "a", MSB16 + offr);
6047 if (size >= MSB24 + offr)
6049 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6051 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6054 emitcode ("rlc", "a");
6055 if (sameRegs (AOP (left), AOP (result)) &&
6056 size >= MSB32 + offr && offr != LSB)
6057 emitcode ("xch", "a,%s",
6058 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6060 aopPut (AOP (result), "a", MSB24 + offr);
6063 if (size > MSB32 + offr)
6065 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6067 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6070 emitcode ("rlc", "a");
6071 aopPut (AOP (result), "a", MSB32 + offr);
6074 aopPut (AOP (result), zero, LSB);
6077 /*-----------------------------------------------------------------*/
6078 /* genlshFour - shift four byte by a known amount != 0 */
6079 /*-----------------------------------------------------------------*/
6081 genlshFour (operand * result, operand * left, int shCount)
6085 size = AOP_SIZE (result);
6087 /* if shifting more that 3 bytes */
6092 /* lowest order of left goes to the highest
6093 order of the destination */
6094 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6096 movLeft2Result (left, LSB, result, MSB32, 0);
6097 aopPut (AOP (result), zero, LSB);
6098 aopPut (AOP (result), zero, MSB16);
6099 aopPut (AOP (result), zero, MSB24);
6103 /* more than two bytes */
6104 else if (shCount >= 16)
6106 /* lower order two bytes goes to higher order two bytes */
6108 /* if some more remaining */
6110 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6113 movLeft2Result (left, MSB16, result, MSB32, 0);
6114 movLeft2Result (left, LSB, result, MSB24, 0);
6116 aopPut (AOP (result), zero, MSB16);
6117 aopPut (AOP (result), zero, LSB);
6121 /* if more than 1 byte */
6122 else if (shCount >= 8)
6124 /* lower order three bytes goes to higher order three bytes */
6129 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6131 movLeft2Result (left, LSB, result, MSB16, 0);
6137 movLeft2Result (left, MSB24, result, MSB32, 0);
6138 movLeft2Result (left, MSB16, result, MSB24, 0);
6139 movLeft2Result (left, LSB, result, MSB16, 0);
6140 aopPut (AOP (result), zero, LSB);
6142 else if (shCount == 1)
6143 shiftLLong (left, result, MSB16);
6146 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6147 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6148 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6149 aopPut (AOP (result), zero, LSB);
6154 /* 1 <= shCount <= 7 */
6155 else if (shCount <= 2)
6157 shiftLLong (left, result, LSB);
6159 shiftLLong (result, result, LSB);
6161 /* 3 <= shCount <= 7, optimize */
6164 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6165 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6166 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6170 /*-----------------------------------------------------------------*/
6171 /* genLeftShiftLiteral - left shifting by known count */
6172 /*-----------------------------------------------------------------*/
6174 genLeftShiftLiteral (operand * left,
6179 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6182 freeAsmop (right, NULL, ic, TRUE);
6184 aopOp (left, ic, FALSE);
6185 aopOp (result, ic, FALSE);
6187 size = getSize (operandType (result));
6190 emitcode ("; shift left ", "result %d, left %d", size,
6194 /* I suppose that the left size >= result size */
6199 movLeft2Result (left, size, result, size, 0);
6203 else if (shCount >= (size * 8))
6205 aopPut (AOP (result), zero, size);
6211 genlshOne (result, left, shCount);
6215 genlshTwo (result, left, shCount);
6219 genlshFour (result, left, shCount);
6222 fprintf(stderr, "*** ack! mystery literal shift!\n");
6226 freeAsmop (left, NULL, ic, TRUE);
6227 freeAsmop (result, NULL, ic, TRUE);
6230 /*-----------------------------------------------------------------*/
6231 /* genLeftShift - generates code for left shifting */
6232 /*-----------------------------------------------------------------*/
6234 genLeftShift (iCode * ic)
6236 operand *left, *right, *result;
6239 symbol *tlbl, *tlbl1;
6241 right = IC_RIGHT (ic);
6242 left = IC_LEFT (ic);
6243 result = IC_RESULT (ic);
6245 aopOp (right, ic, FALSE);
6247 /* if the shift count is known then do it
6248 as efficiently as possible */
6249 if (AOP_TYPE (right) == AOP_LIT)
6251 genLeftShiftLiteral (left, right, result, ic);
6255 /* shift count is unknown then we have to form
6256 a loop get the loop count in B : Note: we take
6257 only the lower order byte since shifting
6258 more that 32 bits make no sense anyway, ( the
6259 largest size of an object can be only 32 bits ) */
6261 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6262 emitcode ("inc", "b");
6263 freeAsmop (right, NULL, ic, TRUE);
6264 aopOp (left, ic, FALSE);
6265 aopOp (result, ic, FALSE);
6267 /* now move the left to the result if they are not the
6269 if (!sameRegs (AOP (left), AOP (result)) &&
6270 AOP_SIZE (result) > 1)
6273 size = AOP_SIZE (result);
6277 l = aopGet (AOP (left), offset, FALSE, TRUE);
6278 if (*l == '@' && (IS_AOP_PREG (result)))
6281 emitcode ("mov", "a,%s", l);
6282 aopPut (AOP (result), "a", offset);
6285 aopPut (AOP (result), l, offset);
6290 tlbl = newiTempLabel (NULL);
6291 size = AOP_SIZE (result);
6293 tlbl1 = newiTempLabel (NULL);
6295 /* if it is only one byte then */
6298 symbol *tlbl1 = newiTempLabel (NULL);
6300 l = aopGet (AOP (left), 0, FALSE, FALSE);
6302 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6303 emitcode ("", "%05d$:", tlbl->key + 100);
6304 emitcode ("add", "a,acc");
6305 emitcode ("", "%05d$:", tlbl1->key + 100);
6306 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6307 aopPut (AOP (result), "a", 0);
6311 reAdjustPreg (AOP (result));
6313 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6314 emitcode ("", "%05d$:", tlbl->key + 100);
6315 l = aopGet (AOP (result), offset, FALSE, FALSE);
6317 emitcode ("add", "a,acc");
6318 aopPut (AOP (result), "a", offset++);
6321 l = aopGet (AOP (result), offset, FALSE, FALSE);
6323 emitcode ("rlc", "a");
6324 aopPut (AOP (result), "a", offset++);
6326 reAdjustPreg (AOP (result));
6328 emitcode ("", "%05d$:", tlbl1->key + 100);
6329 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6331 freeAsmop (left, NULL, ic, TRUE);
6332 freeAsmop (result, NULL, ic, TRUE);
6335 /*-----------------------------------------------------------------*/
6336 /* genrshOne - right shift a one byte quantity by known count */
6337 /*-----------------------------------------------------------------*/
6339 genrshOne (operand * result, operand * left,
6340 int shCount, int sign)
6342 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6345 /*-----------------------------------------------------------------*/
6346 /* genrshTwo - right shift two bytes by known amount != 0 */
6347 /*-----------------------------------------------------------------*/
6349 genrshTwo (operand * result, operand * left,
6350 int shCount, int sign)
6352 /* if shCount >= 8 */
6357 shiftR1Left2Result (left, MSB16, result, LSB,
6360 movLeft2Result (left, MSB16, result, LSB, sign);
6361 addSign (result, MSB16, sign);
6364 /* 1 <= shCount <= 7 */
6366 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6369 /*-----------------------------------------------------------------*/
6370 /* shiftRLong - shift right one long from left to result */
6371 /* offl = LSB or MSB16 */
6372 /*-----------------------------------------------------------------*/
6374 shiftRLong (operand * left, int offl,
6375 operand * result, int sign)
6377 int isSameRegs=sameRegs(AOP(left),AOP(result));
6379 if (isSameRegs && offl>1) {
6380 // we are in big trouble, but this shouldn't happen
6381 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6384 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6389 emitcode ("rlc", "a");
6390 emitcode ("subb", "a,acc");
6391 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6393 aopPut (AOP(result), zero, MSB32);
6398 emitcode ("clr", "c");
6400 emitcode ("mov", "c,acc.7");
6403 emitcode ("rrc", "a");
6405 if (isSameRegs && offl==MSB16) {
6406 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6408 aopPut (AOP (result), "a", MSB32);
6409 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6412 emitcode ("rrc", "a");
6413 if (isSameRegs && offl==1) {
6414 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6416 aopPut (AOP (result), "a", MSB24);
6417 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6419 emitcode ("rrc", "a");
6420 aopPut (AOP (result), "a", MSB16 - offl);
6424 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6425 emitcode ("rrc", "a");
6426 aopPut (AOP (result), "a", LSB);
6430 /*-----------------------------------------------------------------*/
6431 /* genrshFour - shift four byte by a known amount != 0 */
6432 /*-----------------------------------------------------------------*/
6434 genrshFour (operand * result, operand * left,
6435 int shCount, int sign)
6437 /* if shifting more that 3 bytes */
6442 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6444 movLeft2Result (left, MSB32, result, LSB, sign);
6445 addSign (result, MSB16, sign);
6447 else if (shCount >= 16)
6451 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6454 movLeft2Result (left, MSB24, result, LSB, 0);
6455 movLeft2Result (left, MSB32, result, MSB16, sign);
6457 addSign (result, MSB24, sign);
6459 else if (shCount >= 8)
6463 shiftRLong (left, MSB16, result, sign);
6464 else if (shCount == 0)
6466 movLeft2Result (left, MSB16, result, LSB, 0);
6467 movLeft2Result (left, MSB24, result, MSB16, 0);
6468 movLeft2Result (left, MSB32, result, MSB24, sign);
6469 addSign (result, MSB32, sign);
6473 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6474 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6475 /* the last shift is signed */
6476 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6477 addSign (result, MSB32, sign);
6481 { /* 1 <= shCount <= 7 */
6484 shiftRLong (left, LSB, result, sign);
6486 shiftRLong (result, LSB, result, sign);
6490 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6491 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6492 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6497 /*-----------------------------------------------------------------*/
6498 /* genRightShiftLiteral - right shifting by known count */
6499 /*-----------------------------------------------------------------*/
6501 genRightShiftLiteral (operand * left,
6507 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6510 freeAsmop (right, NULL, ic, TRUE);
6512 aopOp (left, ic, FALSE);
6513 aopOp (result, ic, FALSE);
6516 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6520 size = getDataSize (left);
6521 /* test the LEFT size !!! */
6523 /* I suppose that the left size >= result size */
6526 size = getDataSize (result);
6528 movLeft2Result (left, size, result, size, 0);
6531 else if (shCount >= (size * 8))
6534 /* get sign in acc.7 */
6535 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6536 addSign (result, LSB, sign);
6543 genrshOne (result, left, shCount, sign);
6547 genrshTwo (result, left, shCount, sign);
6551 genrshFour (result, left, shCount, sign);
6557 freeAsmop (left, NULL, ic, TRUE);
6558 freeAsmop (result, NULL, ic, TRUE);
6562 /*-----------------------------------------------------------------*/
6563 /* genSignedRightShift - right shift of signed number */
6564 /*-----------------------------------------------------------------*/
6566 genSignedRightShift (iCode * ic)
6568 operand *right, *left, *result;
6571 symbol *tlbl, *tlbl1;
6573 /* we do it the hard way put the shift count in b
6574 and loop thru preserving the sign */
6576 right = IC_RIGHT (ic);
6577 left = IC_LEFT (ic);
6578 result = IC_RESULT (ic);
6580 aopOp (right, ic, FALSE);
6583 if (AOP_TYPE (right) == AOP_LIT)
6585 genRightShiftLiteral (left, right, result, ic, 1);
6588 /* shift count is unknown then we have to form
6589 a loop get the loop count in B : Note: we take
6590 only the lower order byte since shifting
6591 more that 32 bits make no sense anyway, ( the
6592 largest size of an object can be only 32 bits ) */
6594 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6595 emitcode ("inc", "b");
6596 freeAsmop (right, NULL, ic, TRUE);
6597 aopOp (left, ic, FALSE);
6598 aopOp (result, ic, FALSE);
6600 /* now move the left to the result if they are not the
6602 if (!sameRegs (AOP (left), AOP (result)) &&
6603 AOP_SIZE (result) > 1)
6606 size = AOP_SIZE (result);
6610 l = aopGet (AOP (left), offset, FALSE, TRUE);
6611 if (*l == '@' && IS_AOP_PREG (result))
6614 emitcode ("mov", "a,%s", l);
6615 aopPut (AOP (result), "a", offset);
6618 aopPut (AOP (result), l, offset);
6623 /* mov the highest order bit to OVR */
6624 tlbl = newiTempLabel (NULL);
6625 tlbl1 = newiTempLabel (NULL);
6627 size = AOP_SIZE (result);
6629 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6630 emitcode ("rlc", "a");
6631 emitcode ("mov", "ov,c");
6632 /* if it is only one byte then */
6635 l = aopGet (AOP (left), 0, FALSE, FALSE);
6637 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6638 emitcode ("", "%05d$:", tlbl->key + 100);
6639 emitcode ("mov", "c,ov");
6640 emitcode ("rrc", "a");
6641 emitcode ("", "%05d$:", tlbl1->key + 100);
6642 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6643 aopPut (AOP (result), "a", 0);
6647 reAdjustPreg (AOP (result));
6648 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6649 emitcode ("", "%05d$:", tlbl->key + 100);
6650 emitcode ("mov", "c,ov");
6653 l = aopGet (AOP (result), offset, FALSE, FALSE);
6655 emitcode ("rrc", "a");
6656 aopPut (AOP (result), "a", offset--);
6658 reAdjustPreg (AOP (result));
6659 emitcode ("", "%05d$:", tlbl1->key + 100);
6660 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6663 freeAsmop (left, NULL, ic, TRUE);
6664 freeAsmop (result, NULL, ic, TRUE);
6667 /*-----------------------------------------------------------------*/
6668 /* genRightShift - generate code for right shifting */
6669 /*-----------------------------------------------------------------*/
6671 genRightShift (iCode * ic)
6673 operand *right, *left, *result;
6677 symbol *tlbl, *tlbl1;
6679 /* if signed then we do it the hard way preserve the
6680 sign bit moving it inwards */
6681 retype = getSpec (operandType (IC_RESULT (ic)));
6683 if (!SPEC_USIGN (retype))
6685 genSignedRightShift (ic);
6689 /* signed & unsigned types are treated the same : i.e. the
6690 signed is NOT propagated inwards : quoting from the
6691 ANSI - standard : "for E1 >> E2, is equivalent to division
6692 by 2**E2 if unsigned or if it has a non-negative value,
6693 otherwise the result is implementation defined ", MY definition
6694 is that the sign does not get propagated */
6696 right = IC_RIGHT (ic);
6697 left = IC_LEFT (ic);
6698 result = IC_RESULT (ic);
6700 aopOp (right, ic, FALSE);
6702 /* if the shift count is known then do it
6703 as efficiently as possible */
6704 if (AOP_TYPE (right) == AOP_LIT)
6706 genRightShiftLiteral (left, right, result, ic, 0);
6710 /* shift count is unknown then we have to form
6711 a loop get the loop count in B : Note: we take
6712 only the lower order byte since shifting
6713 more that 32 bits make no sense anyway, ( the
6714 largest size of an object can be only 32 bits ) */
6716 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6717 emitcode ("inc", "b");
6718 freeAsmop (right, NULL, ic, TRUE);
6719 aopOp (left, ic, FALSE);
6720 aopOp (result, ic, FALSE);
6722 /* now move the left to the result if they are not the
6724 if (!sameRegs (AOP (left), AOP (result)) &&
6725 AOP_SIZE (result) > 1)
6728 size = AOP_SIZE (result);
6732 l = aopGet (AOP (left), offset, FALSE, TRUE);
6733 if (*l == '@' && IS_AOP_PREG (result))
6736 emitcode ("mov", "a,%s", l);
6737 aopPut (AOP (result), "a", offset);
6740 aopPut (AOP (result), l, offset);
6745 tlbl = newiTempLabel (NULL);
6746 tlbl1 = newiTempLabel (NULL);
6747 size = AOP_SIZE (result);
6750 /* if it is only one byte then */
6753 l = aopGet (AOP (left), 0, FALSE, FALSE);
6755 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6756 emitcode ("", "%05d$:", tlbl->key + 100);
6758 emitcode ("rrc", "a");
6759 emitcode ("", "%05d$:", tlbl1->key + 100);
6760 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6761 aopPut (AOP (result), "a", 0);
6765 reAdjustPreg (AOP (result));
6766 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6767 emitcode ("", "%05d$:", tlbl->key + 100);
6771 l = aopGet (AOP (result), offset, FALSE, FALSE);
6773 emitcode ("rrc", "a");
6774 aopPut (AOP (result), "a", offset--);
6776 reAdjustPreg (AOP (result));
6778 emitcode ("", "%05d$:", tlbl1->key + 100);
6779 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6782 freeAsmop (left, NULL, ic, TRUE);
6783 freeAsmop (result, NULL, ic, TRUE);
6786 /*-----------------------------------------------------------------*/
6787 /* genUnpackBits - generates code for unpacking bits */
6788 /*-----------------------------------------------------------------*/
6790 genUnpackBits (operand * result, char *rname, int ptype)
6798 etype = getSpec (operandType (result));
6799 rsize = getSize (operandType (result));
6800 /* read the first byte */
6806 emitcode ("mov", "a,@%s", rname);
6810 emitcode ("movx", "a,@%s", rname);
6814 emitcode ("movx", "a,@dptr");
6818 emitcode ("clr", "a");
6819 emitcode ("movc", "a,@a+dptr");
6823 emitcode ("lcall", "__gptrget");
6827 rlen = SPEC_BLEN (etype);
6829 /* if we have bitdisplacement then it fits */
6830 /* into this byte completely or if length is */
6831 /* less than a byte */
6832 if ((shCnt = SPEC_BSTR (etype)) ||
6833 (SPEC_BLEN (etype) <= 8))
6836 /* shift right acc */
6839 emitcode ("anl", "a,#0x%02x",
6840 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6841 aopPut (AOP (result), "a", offset++);
6845 /* bit field did not fit in a byte */
6846 aopPut (AOP (result), "a", offset++);
6855 emitcode ("inc", "%s", rname);
6856 emitcode ("mov", "a,@%s", rname);
6860 emitcode ("inc", "%s", rname);
6861 emitcode ("movx", "a,@%s", rname);
6865 emitcode ("inc", "dptr");
6866 emitcode ("movx", "a,@dptr");
6870 emitcode ("clr", "a");
6871 emitcode ("inc", "dptr");
6872 emitcode ("movc", "a,@a+dptr");
6876 emitcode ("inc", "dptr");
6877 emitcode ("lcall", "__gptrget");
6882 /* if we are done */
6886 aopPut (AOP (result), "a", offset++);
6892 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6894 aopPut (AOP (result), "a", offset++);
6902 aopPut (AOP (result), zero, offset++);
6908 /*-----------------------------------------------------------------*/
6909 /* genDataPointerGet - generates code when ptr offset is known */
6910 /*-----------------------------------------------------------------*/
6912 genDataPointerGet (operand * left,
6918 int size, offset = 0;
6919 aopOp (result, ic, TRUE);
6921 /* get the string representation of the name */
6922 l = aopGet (AOP (left), 0, FALSE, TRUE);
6923 size = AOP_SIZE (result);
6927 sprintf (buffer, "(%s + %d)", l + 1, offset);
6929 sprintf (buffer, "%s", l + 1);
6930 aopPut (AOP (result), buffer, offset++);
6933 freeAsmop (left, NULL, ic, TRUE);
6934 freeAsmop (result, NULL, ic, TRUE);
6937 /*-----------------------------------------------------------------*/
6938 /* genNearPointerGet - emitcode for near pointer fetch */
6939 /*-----------------------------------------------------------------*/
6941 genNearPointerGet (operand * left,
6949 sym_link *rtype, *retype;
6950 sym_link *ltype = operandType (left);
6953 rtype = operandType (result);
6954 retype = getSpec (rtype);
6956 aopOp (left, ic, FALSE);
6958 /* if left is rematerialisable and
6959 result is not bit variable type and
6960 the left is pointer to data space i.e
6961 lower 128 bytes of space */
6962 if (AOP_TYPE (left) == AOP_IMMD &&
6963 !IS_BITVAR (retype) &&
6964 DCL_TYPE (ltype) == POINTER)
6966 genDataPointerGet (left, result, ic);
6970 /* if the value is already in a pointer register
6971 then don't need anything more */
6972 if (!AOP_INPREG (AOP (left)))
6974 /* otherwise get a free pointer register */
6976 preg = getFreePtr (ic, &aop, FALSE);
6977 emitcode ("mov", "%s,%s",
6979 aopGet (AOP (left), 0, FALSE, TRUE));
6983 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6985 //aopOp (result, ic, FALSE);
6986 aopOp (result, ic, result?TRUE:FALSE);
6988 /* if bitfield then unpack the bits */
6989 if (IS_BITVAR (retype))
6990 genUnpackBits (result, rname, POINTER);
6993 /* we have can just get the values */
6994 int size = AOP_SIZE (result);
6999 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7002 emitcode ("mov", "a,@%s", rname);
7003 aopPut (AOP (result), "a", offset);
7007 sprintf (buffer, "@%s", rname);
7008 aopPut (AOP (result), buffer, offset);
7012 emitcode ("inc", "%s", rname);
7016 /* now some housekeeping stuff */
7017 if (aop) /* we had to allocate for this iCode */
7019 if (pi) { /* post increment present */
7020 aopPut(AOP ( left ),rname,0);
7022 freeAsmop (NULL, aop, ic, TRUE);
7026 /* we did not allocate which means left
7027 already in a pointer register, then
7028 if size > 0 && this could be used again
7029 we have to point it back to where it
7031 if ((AOP_SIZE (result) > 1 &&
7032 !OP_SYMBOL (left)->remat &&
7033 (OP_SYMBOL (left)->liveTo > ic->seq ||
7037 int size = AOP_SIZE (result) - 1;
7039 emitcode ("dec", "%s", rname);
7044 freeAsmop (left, NULL, ic, TRUE);
7045 freeAsmop (result, NULL, ic, TRUE);
7046 if (pi) pi->generated = 1;
7049 /*-----------------------------------------------------------------*/
7050 /* genPagedPointerGet - emitcode for paged pointer fetch */
7051 /*-----------------------------------------------------------------*/
7053 genPagedPointerGet (operand * left,
7061 sym_link *rtype, *retype;
7063 rtype = operandType (result);
7064 retype = getSpec (rtype);
7066 aopOp (left, ic, FALSE);
7068 /* if the value is already in a pointer register
7069 then don't need anything more */
7070 if (!AOP_INPREG (AOP (left)))
7072 /* otherwise get a free pointer register */
7074 preg = getFreePtr (ic, &aop, FALSE);
7075 emitcode ("mov", "%s,%s",
7077 aopGet (AOP (left), 0, FALSE, TRUE));
7081 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7083 aopOp (result, ic, FALSE);
7085 /* if bitfield then unpack the bits */
7086 if (IS_BITVAR (retype))
7087 genUnpackBits (result, rname, PPOINTER);
7090 /* we have can just get the values */
7091 int size = AOP_SIZE (result);
7097 emitcode ("movx", "a,@%s", rname);
7098 aopPut (AOP (result), "a", offset);
7103 emitcode ("inc", "%s", rname);
7107 /* now some housekeeping stuff */
7108 if (aop) /* we had to allocate for this iCode */
7110 if (pi) aopPut ( AOP (left), rname, 0);
7111 freeAsmop (NULL, aop, ic, TRUE);
7115 /* we did not allocate which means left
7116 already in a pointer register, then
7117 if size > 0 && this could be used again
7118 we have to point it back to where it
7120 if ((AOP_SIZE (result) > 1 &&
7121 !OP_SYMBOL (left)->remat &&
7122 (OP_SYMBOL (left)->liveTo > ic->seq ||
7126 int size = AOP_SIZE (result) - 1;
7128 emitcode ("dec", "%s", rname);
7133 freeAsmop (left, NULL, ic, TRUE);
7134 freeAsmop (result, NULL, ic, TRUE);
7135 if (pi) pi->generated = 1;
7139 /*-----------------------------------------------------------------*/
7140 /* genFarPointerGet - gget value from far space */
7141 /*-----------------------------------------------------------------*/
7143 genFarPointerGet (operand * left,
7144 operand * result, iCode * ic, iCode * pi)
7147 sym_link *retype = getSpec (operandType (result));
7149 aopOp (left, ic, FALSE);
7151 /* if the operand is already in dptr
7152 then we do nothing else we move the value to dptr */
7153 if (AOP_TYPE (left) != AOP_STR)
7155 /* if this is remateriazable */
7156 if (AOP_TYPE (left) == AOP_IMMD)
7157 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7159 { /* we need to get it byte by byte */
7160 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7161 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7164 /* so dptr know contains the address */
7165 aopOp (result, ic, FALSE);
7167 /* if bit then unpack */
7168 if (IS_BITVAR (retype))
7169 genUnpackBits (result, "dptr", FPOINTER);
7172 size = AOP_SIZE (result);
7177 emitcode ("movx", "a,@dptr");
7178 aopPut (AOP (result), "a", offset++);
7180 emitcode ("inc", "dptr");
7184 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7185 aopPut ( AOP (left), "dpl", 0);
7186 aopPut ( AOP (left), "dph", 1);
7189 freeAsmop (left, NULL, ic, TRUE);
7190 freeAsmop (result, NULL, ic, TRUE);
7193 /*-----------------------------------------------------------------*/
7194 /* genCodePointerGet - gget value from code space */
7195 /*-----------------------------------------------------------------*/
7197 genCodePointerGet (operand * left,
7198 operand * result, iCode * ic, iCode *pi)
7201 sym_link *retype = getSpec (operandType (result));
7203 aopOp (left, ic, FALSE);
7205 /* if the operand is already in dptr
7206 then we do nothing else we move the value to dptr */
7207 if (AOP_TYPE (left) != AOP_STR)
7209 /* if this is remateriazable */
7210 if (AOP_TYPE (left) == AOP_IMMD)
7211 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7213 { /* we need to get it byte by byte */
7214 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7215 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7218 /* so dptr know contains the address */
7219 aopOp (result, ic, FALSE);
7221 /* if bit then unpack */
7222 if (IS_BITVAR (retype))
7223 genUnpackBits (result, "dptr", CPOINTER);
7226 size = AOP_SIZE (result);
7231 emitcode ("clr", "a");
7232 emitcode ("movc", "a,@a+dptr");
7233 aopPut (AOP (result), "a", offset++);
7235 emitcode ("inc", "dptr");
7239 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7240 aopPut ( AOP (left), "dpl", 0);
7241 aopPut ( AOP (left), "dph", 1);
7244 freeAsmop (left, NULL, ic, TRUE);
7245 freeAsmop (result, NULL, ic, TRUE);
7248 /*-----------------------------------------------------------------*/
7249 /* genGenPointerGet - gget value from generic pointer space */
7250 /*-----------------------------------------------------------------*/
7252 genGenPointerGet (operand * left,
7253 operand * result, iCode * ic, iCode *pi)
7256 sym_link *retype = getSpec (operandType (result));
7258 aopOp (left, ic, FALSE);
7260 /* if the operand is already in dptr
7261 then we do nothing else we move the value to dptr */
7262 if (AOP_TYPE (left) != AOP_STR)
7264 /* if this is remateriazable */
7265 if (AOP_TYPE (left) == AOP_IMMD)
7267 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7268 emitcode ("mov", "b,#%d", pointerCode (retype));
7271 { /* we need to get it byte by byte */
7272 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7273 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7274 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7277 /* so dptr know contains the address */
7278 aopOp (result, ic, FALSE);
7280 /* if bit then unpack */
7281 if (IS_BITVAR (retype))
7282 genUnpackBits (result, "dptr", GPOINTER);
7285 size = AOP_SIZE (result);
7290 emitcode ("lcall", "__gptrget");
7291 aopPut (AOP (result), "a", offset++);
7293 emitcode ("inc", "dptr");
7297 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7298 aopPut ( AOP (left), "dpl", 0);
7299 aopPut ( AOP (left), "dph", 1);
7302 freeAsmop (left, NULL, ic, TRUE);
7303 freeAsmop (result, NULL, ic, TRUE);
7306 /*-----------------------------------------------------------------*/
7307 /* genPointerGet - generate code for pointer get */
7308 /*-----------------------------------------------------------------*/
7310 genPointerGet (iCode * ic, iCode *pi)
7312 operand *left, *result;
7313 sym_link *type, *etype;
7316 left = IC_LEFT (ic);
7317 result = IC_RESULT (ic);
7319 /* depending on the type of pointer we need to
7320 move it to the correct pointer register */
7321 type = operandType (left);
7322 etype = getSpec (type);
7323 /* if left is of type of pointer then it is simple */
7324 if (IS_PTR (type) && !IS_FUNC (type->next))
7325 p_type = DCL_TYPE (type);
7328 /* we have to go by the storage class */
7329 p_type = PTR_TYPE (SPEC_OCLS (etype));
7332 /* now that we have the pointer type we assign
7333 the pointer values */
7339 genNearPointerGet (left, result, ic, pi);
7343 genPagedPointerGet (left, result, ic, pi);
7347 genFarPointerGet (left, result, ic, pi);
7351 genCodePointerGet (left, result, ic, pi);
7355 genGenPointerGet (left, result, ic, pi);
7361 /*-----------------------------------------------------------------*/
7362 /* genPackBits - generates code for packed bit storage */
7363 /*-----------------------------------------------------------------*/
7365 genPackBits (sym_link * etype,
7367 char *rname, int p_type)
7375 blen = SPEC_BLEN (etype);
7376 bstr = SPEC_BSTR (etype);
7378 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7381 /* if the bit lenth is less than or */
7382 /* it exactly fits a byte then */
7383 if (SPEC_BLEN (etype) <= 8)
7385 shCount = SPEC_BSTR (etype);
7387 /* shift left acc */
7390 if (SPEC_BLEN (etype) < 8)
7391 { /* if smaller than a byte */
7397 emitcode ("mov", "b,a");
7398 emitcode ("mov", "a,@%s", rname);
7402 emitcode ("mov", "b,a");
7403 emitcode ("movx", "a,@dptr");
7407 emitcode ("push", "b");
7408 emitcode ("push", "acc");
7409 emitcode ("lcall", "__gptrget");
7410 emitcode ("pop", "b");
7414 emitcode ("anl", "a,#0x%02x", (unsigned char)
7415 ((unsigned char) (0xFF << (blen + bstr)) |
7416 (unsigned char) (0xFF >> (8 - bstr))));
7417 emitcode ("orl", "a,b");
7418 if (p_type == GPOINTER)
7419 emitcode ("pop", "b");
7426 emitcode ("mov", "@%s,a", rname);
7430 emitcode ("movx", "@dptr,a");
7434 emitcode ("lcall", "__gptrput");
7439 if (SPEC_BLEN (etype) <= 8)
7442 emitcode ("inc", "%s", rname);
7443 rLen = SPEC_BLEN (etype);
7445 /* now generate for lengths greater than one byte */
7449 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7461 emitcode ("mov", "@%s,a", rname);
7464 emitcode ("mov", "@%s,%s", rname, l);
7469 emitcode ("movx", "@dptr,a");
7474 emitcode ("lcall", "__gptrput");
7477 emitcode ("inc", "%s", rname);
7482 /* last last was not complete */
7485 /* save the byte & read byte */
7489 emitcode ("mov", "b,a");
7490 emitcode ("mov", "a,@%s", rname);
7494 emitcode ("mov", "b,a");
7495 emitcode ("movx", "a,@dptr");
7499 emitcode ("push", "b");
7500 emitcode ("push", "acc");
7501 emitcode ("lcall", "__gptrget");
7502 emitcode ("pop", "b");
7506 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7507 emitcode ("orl", "a,b");
7510 if (p_type == GPOINTER)
7511 emitcode ("pop", "b");
7517 emitcode ("mov", "@%s,a", rname);
7521 emitcode ("movx", "@dptr,a");
7525 emitcode ("lcall", "__gptrput");
7529 /*-----------------------------------------------------------------*/
7530 /* genDataPointerSet - remat pointer to data space */
7531 /*-----------------------------------------------------------------*/
7533 genDataPointerSet (operand * right,
7537 int size, offset = 0;
7538 char *l, buffer[256];
7540 aopOp (right, ic, FALSE);
7542 l = aopGet (AOP (result), 0, FALSE, TRUE);
7543 size = AOP_SIZE (right);
7547 sprintf (buffer, "(%s + %d)", l + 1, offset);
7549 sprintf (buffer, "%s", l + 1);
7550 emitcode ("mov", "%s,%s", buffer,
7551 aopGet (AOP (right), offset++, FALSE, FALSE));
7554 freeAsmop (right, NULL, ic, TRUE);
7555 freeAsmop (result, NULL, ic, TRUE);
7558 /*-----------------------------------------------------------------*/
7559 /* genNearPointerSet - emitcode for near pointer put */
7560 /*-----------------------------------------------------------------*/
7562 genNearPointerSet (operand * right,
7570 sym_link *retype, *letype;
7571 sym_link *ptype = operandType (result);
7573 retype = getSpec (operandType (right));
7574 letype = getSpec (ptype);
7575 aopOp (result, ic, FALSE);
7577 /* if the result is rematerializable &
7578 in data space & not a bit variable */
7579 if (AOP_TYPE (result) == AOP_IMMD &&
7580 DCL_TYPE (ptype) == POINTER &&
7581 !IS_BITVAR (retype) &&
7582 !IS_BITVAR (letype))
7584 genDataPointerSet (right, result, ic);
7588 /* if the value is already in a pointer register
7589 then don't need anything more */
7590 if (!AOP_INPREG (AOP (result)))
7593 //AOP_TYPE (result) == AOP_STK
7597 // Aha, it is a pointer, just in disguise.
7598 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7601 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7602 __FILE__, __LINE__);
7607 rname++; // skip the '@'.
7612 /* otherwise get a free pointer register */
7614 preg = getFreePtr (ic, &aop, FALSE);
7615 emitcode ("mov", "%s,%s",
7617 aopGet (AOP (result), 0, FALSE, TRUE));
7623 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7626 aopOp (right, ic, FALSE);
7628 /* if bitfield then unpack the bits */
7629 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7630 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7633 /* we have can just get the values */
7634 int size = AOP_SIZE (right);
7639 l = aopGet (AOP (right), offset, FALSE, TRUE);
7643 emitcode ("mov", "@%s,a", rname);
7646 emitcode ("mov", "@%s,%s", rname, l);
7648 emitcode ("inc", "%s", rname);
7653 /* now some housekeeping stuff */
7654 if (aop) /* we had to allocate for this iCode */
7656 if (pi) aopPut (AOP (result),rname,0);
7657 freeAsmop (NULL, aop, ic, TRUE);
7661 /* we did not allocate which means left
7662 already in a pointer register, then
7663 if size > 0 && this could be used again
7664 we have to point it back to where it
7666 if ((AOP_SIZE (right) > 1 &&
7667 !OP_SYMBOL (result)->remat &&
7668 (OP_SYMBOL (result)->liveTo > ic->seq ||
7672 int size = AOP_SIZE (right) - 1;
7674 emitcode ("dec", "%s", rname);
7679 if (pi) pi->generated = 1;
7680 freeAsmop (result, NULL, ic, TRUE);
7681 freeAsmop (right, NULL, ic, TRUE);
7684 /*-----------------------------------------------------------------*/
7685 /* genPagedPointerSet - emitcode for Paged pointer put */
7686 /*-----------------------------------------------------------------*/
7688 genPagedPointerSet (operand * right,
7696 sym_link *retype, *letype;
7698 retype = getSpec (operandType (right));
7699 letype = getSpec (operandType (result));
7701 aopOp (result, ic, FALSE);
7703 /* if the value is already in a pointer register
7704 then don't need anything more */
7705 if (!AOP_INPREG (AOP (result)))
7707 /* otherwise get a free pointer register */
7709 preg = getFreePtr (ic, &aop, FALSE);
7710 emitcode ("mov", "%s,%s",
7712 aopGet (AOP (result), 0, FALSE, TRUE));
7716 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7718 aopOp (right, ic, FALSE);
7720 /* if bitfield then unpack the bits */
7721 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7722 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7725 /* we have can just get the values */
7726 int size = AOP_SIZE (right);
7731 l = aopGet (AOP (right), offset, FALSE, TRUE);
7734 emitcode ("movx", "@%s,a", rname);
7737 emitcode ("inc", "%s", rname);
7743 /* now some housekeeping stuff */
7744 if (aop) /* we had to allocate for this iCode */
7746 if (pi) aopPut (AOP (result),rname,0);
7747 freeAsmop (NULL, aop, ic, TRUE);
7751 /* we did not allocate which means left
7752 already in a pointer register, then
7753 if size > 0 && this could be used again
7754 we have to point it back to where it
7756 if (AOP_SIZE (right) > 1 &&
7757 !OP_SYMBOL (result)->remat &&
7758 (OP_SYMBOL (result)->liveTo > ic->seq ||
7761 int size = AOP_SIZE (right) - 1;
7763 emitcode ("dec", "%s", rname);
7768 if (pi) pi->generated = 1;
7769 freeAsmop (result, NULL, ic, TRUE);
7770 freeAsmop (right, NULL, ic, TRUE);
7775 /*-----------------------------------------------------------------*/
7776 /* genFarPointerSet - set value from far space */
7777 /*-----------------------------------------------------------------*/
7779 genFarPointerSet (operand * right,
7780 operand * result, iCode * ic, iCode * pi)
7783 sym_link *retype = getSpec (operandType (right));
7784 sym_link *letype = getSpec (operandType (result));
7785 aopOp (result, ic, FALSE);
7787 /* if the operand is already in dptr
7788 then we do nothing else we move the value to dptr */
7789 if (AOP_TYPE (result) != AOP_STR)
7791 /* if this is remateriazable */
7792 if (AOP_TYPE (result) == AOP_IMMD)
7793 emitcode ("mov", "dptr,%s", 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));
7800 /* so dptr know contains the address */
7801 aopOp (right, ic, FALSE);
7803 /* if bit then unpack */
7804 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7805 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7808 size = AOP_SIZE (right);
7813 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7815 emitcode ("movx", "@dptr,a");
7817 emitcode ("inc", "dptr");
7820 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7821 aopPut (AOP(result),"dpl",0);
7822 aopPut (AOP(result),"dph",1);
7825 freeAsmop (result, NULL, ic, TRUE);
7826 freeAsmop (right, NULL, ic, TRUE);
7829 /*-----------------------------------------------------------------*/
7830 /* genGenPointerSet - set value from generic pointer space */
7831 /*-----------------------------------------------------------------*/
7833 genGenPointerSet (operand * right,
7834 operand * result, iCode * ic, iCode * pi)
7837 sym_link *retype = getSpec (operandType (right));
7838 sym_link *letype = getSpec (operandType (result));
7840 aopOp (result, ic, FALSE);
7842 /* if the operand is already in dptr
7843 then we do nothing else we move the value to dptr */
7844 if (AOP_TYPE (result) != AOP_STR)
7846 /* if this is remateriazable */
7847 if (AOP_TYPE (result) == AOP_IMMD)
7849 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7850 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7853 { /* we need to get it byte by byte */
7854 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7855 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7856 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7859 /* so dptr know contains the address */
7860 aopOp (right, ic, FALSE);
7862 /* if bit then unpack */
7863 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7864 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7867 size = AOP_SIZE (right);
7872 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7874 emitcode ("lcall", "__gptrput");
7876 emitcode ("inc", "dptr");
7880 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7881 aopPut (AOP(result),"dpl",0);
7882 aopPut (AOP(result),"dph",1);
7885 freeAsmop (result, NULL, ic, TRUE);
7886 freeAsmop (right, NULL, ic, TRUE);
7889 /*-----------------------------------------------------------------*/
7890 /* genPointerSet - stores the value into a pointer location */
7891 /*-----------------------------------------------------------------*/
7893 genPointerSet (iCode * ic, iCode *pi)
7895 operand *right, *result;
7896 sym_link *type, *etype;
7899 right = IC_RIGHT (ic);
7900 result = IC_RESULT (ic);
7902 /* depending on the type of pointer we need to
7903 move it to the correct pointer register */
7904 type = operandType (result);
7905 etype = getSpec (type);
7906 /* if left is of type of pointer then it is simple */
7907 if (IS_PTR (type) && !IS_FUNC (type->next))
7909 p_type = DCL_TYPE (type);
7913 /* we have to go by the storage class */
7914 p_type = PTR_TYPE (SPEC_OCLS (etype));
7917 /* now that we have the pointer type we assign
7918 the pointer values */
7924 genNearPointerSet (right, result, ic, pi);
7928 genPagedPointerSet (right, result, ic, pi);
7932 genFarPointerSet (right, result, ic, pi);
7936 genGenPointerSet (right, result, ic, pi);
7942 /*-----------------------------------------------------------------*/
7943 /* genIfx - generate code for Ifx statement */
7944 /*-----------------------------------------------------------------*/
7946 genIfx (iCode * ic, iCode * popIc)
7948 operand *cond = IC_COND (ic);
7951 aopOp (cond, ic, FALSE);
7953 /* get the value into acc */
7954 if (AOP_TYPE (cond) != AOP_CRY)
7958 /* the result is now in the accumulator */
7959 freeAsmop (cond, NULL, ic, TRUE);
7961 /* if there was something to be popped then do it */
7965 /* if the condition is a bit variable */
7966 if (isbit && IS_ITEMP (cond) &&
7968 genIfxJump (ic, SPIL_LOC (cond)->rname);
7969 else if (isbit && !IS_ITEMP (cond))
7970 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7972 genIfxJump (ic, "a");
7977 /*-----------------------------------------------------------------*/
7978 /* genAddrOf - generates code for address of */
7979 /*-----------------------------------------------------------------*/
7981 genAddrOf (iCode * ic)
7983 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7986 aopOp (IC_RESULT (ic), ic, FALSE);
7988 /* if the operand is on the stack then we
7989 need to get the stack offset of this
7993 /* if it has an offset then we need to compute
7997 emitcode ("mov", "a,_bp");
7998 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7999 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8003 /* we can just move _bp */
8004 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8006 /* fill the result with zero */
8007 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8012 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8018 /* object not on stack then we need the name */
8019 size = AOP_SIZE (IC_RESULT (ic));
8024 char s[SDCC_NAME_MAX];
8026 sprintf (s, "#(%s >> %d)",
8030 sprintf (s, "#%s", sym->rname);
8031 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8035 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8039 /*-----------------------------------------------------------------*/
8040 /* genFarFarAssign - assignment when both are in far space */
8041 /*-----------------------------------------------------------------*/
8043 genFarFarAssign (operand * result, operand * right, iCode * ic)
8045 int size = AOP_SIZE (right);
8048 /* first push the right side on to the stack */
8051 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8053 emitcode ("push", "acc");
8056 freeAsmop (right, NULL, ic, FALSE);
8057 /* now assign DPTR to result */
8058 aopOp (result, ic, FALSE);
8059 size = AOP_SIZE (result);
8062 emitcode ("pop", "acc");
8063 aopPut (AOP (result), "a", --offset);
8065 freeAsmop (result, NULL, ic, FALSE);
8069 /*-----------------------------------------------------------------*/
8070 /* genAssign - generate code for assignment */
8071 /*-----------------------------------------------------------------*/
8073 genAssign (iCode * ic)
8075 operand *result, *right;
8077 unsigned long lit = 0L;
8079 D(emitcode(";","genAssign"));
8081 result = IC_RESULT (ic);
8082 right = IC_RIGHT (ic);
8084 /* if they are the same */
8085 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8088 aopOp (right, ic, FALSE);
8090 /* special case both in far space */
8091 if (AOP_TYPE (right) == AOP_DPTR &&
8092 IS_TRUE_SYMOP (result) &&
8093 isOperandInFarSpace (result))
8096 genFarFarAssign (result, right, ic);
8100 aopOp (result, ic, TRUE);
8102 /* if they are the same registers */
8103 if (sameRegs (AOP (right), AOP (result)))
8106 /* if the result is a bit */
8107 if (AOP_TYPE (result) == AOP_CRY)
8110 /* if the right size is a literal then
8111 we know what the value is */
8112 if (AOP_TYPE (right) == AOP_LIT)
8114 if (((int) operandLitValue (right)))
8115 aopPut (AOP (result), one, 0);
8117 aopPut (AOP (result), zero, 0);
8121 /* the right is also a bit variable */
8122 if (AOP_TYPE (right) == AOP_CRY)
8124 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8125 aopPut (AOP (result), "c", 0);
8131 aopPut (AOP (result), "a", 0);
8135 /* bit variables done */
8137 size = AOP_SIZE (result);
8139 if (AOP_TYPE (right) == AOP_LIT)
8140 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8142 (AOP_TYPE (result) != AOP_REG) &&
8143 (AOP_TYPE (right) == AOP_LIT) &&
8144 !IS_FLOAT (operandType (right)) &&
8147 emitcode ("clr", "a");
8150 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8151 aopPut (AOP (result), "a", size);
8153 aopPut (AOP (result),
8154 aopGet (AOP (right), size, FALSE, FALSE),
8162 aopPut (AOP (result),
8163 aopGet (AOP (right), offset, FALSE, FALSE),
8170 freeAsmop (right, NULL, ic, TRUE);
8171 freeAsmop (result, NULL, ic, TRUE);
8174 /*-----------------------------------------------------------------*/
8175 /* genJumpTab - genrates code for jump table */
8176 /*-----------------------------------------------------------------*/
8178 genJumpTab (iCode * ic)
8183 aopOp (IC_JTCOND (ic), ic, FALSE);
8184 /* get the condition into accumulator */
8185 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8187 /* multiply by three */
8188 emitcode ("add", "a,acc");
8189 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8190 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8192 jtab = newiTempLabel (NULL);
8193 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8194 emitcode ("jmp", "@a+dptr");
8195 emitcode ("", "%05d$:", jtab->key + 100);
8196 /* now generate the jump labels */
8197 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8198 jtab = setNextItem (IC_JTLABELS (ic)))
8199 emitcode ("ljmp", "%05d$", jtab->key + 100);
8203 /*-----------------------------------------------------------------*/
8204 /* genCast - gen code for casting */
8205 /*-----------------------------------------------------------------*/
8207 genCast (iCode * ic)
8209 operand *result = IC_RESULT (ic);
8210 sym_link *ctype = operandType (IC_LEFT (ic));
8211 sym_link *rtype = operandType (IC_RIGHT (ic));
8212 operand *right = IC_RIGHT (ic);
8215 D(emitcode(";", "genCast"));
8217 /* if they are equivalent then do nothing */
8218 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8221 aopOp (right, ic, FALSE);
8222 aopOp (result, ic, FALSE);
8224 /* if the result is a bit */
8225 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8226 if (IS_BITVAR(OP_SYMBOL(result)->type))
8228 /* if the right size is a literal then
8229 we know what the value is */
8230 if (AOP_TYPE (right) == AOP_LIT)
8232 if (((int) operandLitValue (right)))
8233 aopPut (AOP (result), one, 0);
8235 aopPut (AOP (result), zero, 0);
8240 /* the right is also a bit variable */
8241 if (AOP_TYPE (right) == AOP_CRY)
8243 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8244 aopPut (AOP (result), "c", 0);
8250 aopPut (AOP (result), "a", 0);
8254 /* if they are the same size : or less */
8255 if (AOP_SIZE (result) <= AOP_SIZE (right))
8258 /* if they are in the same place */
8259 if (sameRegs (AOP (right), AOP (result)))
8262 /* if they in different places then copy */
8263 size = AOP_SIZE (result);
8267 aopPut (AOP (result),
8268 aopGet (AOP (right), offset, FALSE, FALSE),
8276 /* if the result is of type pointer */
8281 sym_link *type = operandType (right);
8282 sym_link *etype = getSpec (type);
8284 /* pointer to generic pointer */
8285 if (IS_GENPTR (ctype))
8290 p_type = DCL_TYPE (type);
8293 if (SPEC_SCLS(etype)==S_REGISTER) {
8294 // let's assume it is a generic pointer
8297 /* we have to go by the storage class */
8298 p_type = PTR_TYPE (SPEC_OCLS (etype));
8302 /* the first two bytes are known */
8303 size = GPTRSIZE - 1;
8307 aopPut (AOP (result),
8308 aopGet (AOP (right), offset, FALSE, FALSE),
8312 /* the last byte depending on type */
8328 case PPOINTER: // what the fck is this?
8333 /* this should never happen */
8334 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8335 "got unknown pointer type");
8338 aopPut (AOP (result), l, GPTRSIZE - 1);
8342 /* just copy the pointers */
8343 size = AOP_SIZE (result);
8347 aopPut (AOP (result),
8348 aopGet (AOP (right), offset, FALSE, FALSE),
8355 /* so we now know that the size of destination is greater
8356 than the size of the source */
8357 /* we move to result for the size of source */
8358 size = AOP_SIZE (right);
8362 aopPut (AOP (result),
8363 aopGet (AOP (right), offset, FALSE, FALSE),
8368 /* now depending on the sign of the source && destination */
8369 size = AOP_SIZE (result) - AOP_SIZE (right);
8370 /* if unsigned or not an integral type */
8371 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8374 aopPut (AOP (result), zero, offset++);
8378 /* we need to extend the sign :{ */
8379 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8382 emitcode ("rlc", "a");
8383 emitcode ("subb", "a,acc");
8385 aopPut (AOP (result), "a", offset++);
8388 /* we are done hurray !!!! */
8391 freeAsmop (right, NULL, ic, TRUE);
8392 freeAsmop (result, NULL, ic, TRUE);
8396 /*-----------------------------------------------------------------*/
8397 /* genDjnz - generate decrement & jump if not zero instrucion */
8398 /*-----------------------------------------------------------------*/
8400 genDjnz (iCode * ic, iCode * ifx)
8406 /* if the if condition has a false label
8407 then we cannot save */
8411 /* if the minus is not of the form
8413 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8414 !IS_OP_LITERAL (IC_RIGHT (ic)))
8417 if (operandLitValue (IC_RIGHT (ic)) != 1)
8420 /* if the size of this greater than one then no
8422 if (getSize (operandType (IC_RESULT (ic))) > 1)
8425 /* otherwise we can save BIG */
8426 lbl = newiTempLabel (NULL);
8427 lbl1 = newiTempLabel (NULL);
8429 aopOp (IC_RESULT (ic), ic, FALSE);
8431 if (AOP_NEEDSACC(IC_RESULT(ic)))
8433 /* If the result is accessed indirectly via
8434 * the accumulator, we must explicitly write
8435 * it back after the decrement.
8437 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8439 if (strcmp(rByte, "a"))
8441 /* Something is hopelessly wrong */
8442 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8443 __FILE__, __LINE__);
8444 /* We can just give up; the generated code will be inefficient,
8447 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8450 emitcode ("dec", "%s", rByte);
8451 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8452 emitcode ("jnz", "%05d$", lbl->key + 100);
8454 else if (IS_AOP_PREG (IC_RESULT (ic)))
8456 emitcode ("dec", "%s",
8457 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8458 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8459 emitcode ("jnz", "%05d$", lbl->key + 100);
8463 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8466 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8467 emitcode ("", "%05d$:", lbl->key + 100);
8468 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8469 emitcode ("", "%05d$:", lbl1->key + 100);
8471 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8476 /*-----------------------------------------------------------------*/
8477 /* genReceive - generate code for a receive iCode */
8478 /*-----------------------------------------------------------------*/
8480 genReceive (iCode * ic)
8482 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8483 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8484 IS_TRUE_SYMOP (IC_RESULT (ic))))
8487 int size = getSize (operandType (IC_RESULT (ic)));
8488 int offset = fReturnSizeMCS51 - size;
8491 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8492 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8495 aopOp (IC_RESULT (ic), ic, FALSE);
8496 size = AOP_SIZE (IC_RESULT (ic));
8500 emitcode ("pop", "acc");
8501 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8508 aopOp (IC_RESULT (ic), ic, FALSE);
8510 assignResultValue (IC_RESULT (ic));
8513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* gen51AggregateAssign - copy complete array's or structures */
8518 /*-----------------------------------------------------------------*/
8519 void gen51AggregateAssign(iCode *ic) {
8520 operand *left=IC_LEFT(ic);
8521 operand *right=IC_RIGHT(ic);
8522 char *fromName=OP_SYMBOL(right)->rname;
8523 char *toName=OP_SYMBOL(left)->rname;
8524 int fromSize=getSize(OP_SYMBOL(right)->type);
8525 int toSize=getSize(OP_SYMBOL(left)->type);
8528 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8529 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8530 // well, this code isn't used yet from anywhere else as for initialising
8531 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8535 if (fromSize!=toSize) {
8536 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8537 ic->filename, ic->lineno);
8542 // use the generic memcpy() for now
8543 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8544 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8545 emitcode ("mov", "a,#%s", fromName);
8546 emitcode ("movx", "@dptr,a");
8547 emitcode ("inc", "dptr");
8548 emitcode ("mov", "a,#(%s>>8)", fromName);
8549 emitcode ("movx", "@dptr,a");
8550 emitcode ("inc", "dptr");
8551 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8552 emitcode ("movx", "@dptr,a");
8553 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8554 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8555 emitcode ("movx", "@dptr,a");
8556 emitcode ("inc", "dptr");
8557 emitcode ("mov", "a,#(%d>>8)", count);
8558 emitcode ("movx", "@dptr,a");
8559 emitcode ("mov", "dptr,#%s", toName);
8560 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8561 emitcode ("lcall", "_memcpy");
8563 // more efficient, but will require the native_memcpy_cs2xs
8564 emitcode ("mov", "r0,#%s", fromName);
8565 emitcode ("mov", "r1,#(%s>>8)", fromName);
8566 emitcode ("mov", "r2,#%s", toName);
8567 emitcode ("mov", "r3,#(%s>>8)", toName);
8568 emitcode ("mov", "r4,#%d", count);
8569 emitcode ("mov", "r5,#(%d>>8)", count);
8570 emitcode ("lcall", "_native_memcpy_cs2xs");
8574 /*-----------------------------------------------------------------*/
8575 /* gen51Code - generate code for 8051 based controllers */
8576 /*-----------------------------------------------------------------*/
8578 gen51Code (iCode * lic)
8583 lineHead = lineCurr = NULL;
8585 /* print the allocation information */
8587 printAllocInfo (currFunc, codeOutFile);
8588 /* if debug information required */
8589 /* if (options.debug && currFunc) { */
8590 if (options.debug && currFunc)
8592 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8594 if (IS_STATIC (currFunc->etype))
8595 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8597 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8600 /* stack pointer name */
8601 if (options.useXstack)
8607 for (ic = lic; ic; ic = ic->next)
8610 if (cln != ic->lineno)
8615 emitcode ("", "C$%s$%d$%d$%d ==.",
8616 FileBaseName (ic->filename), ic->lineno,
8617 ic->level, ic->block);
8620 emitcode (";", "%s %d", ic->filename, ic->lineno);
8623 /* if the result is marked as
8624 spilt and rematerializable or code for
8625 this has already been generated then
8627 if (resultRemat (ic) || ic->generated)
8630 /* depending on the operation */
8650 /* IPOP happens only when trying to restore a
8651 spilt live range, if there is an ifx statement
8652 following this pop then the if statement might
8653 be using some of the registers being popped which
8654 would destory the contents of the register so
8655 we need to check for this condition and handle it */
8657 ic->next->op == IFX &&
8658 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8659 genIfx (ic->next, ic);
8677 genEndFunction (ic);
8697 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8714 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8718 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8725 /* note these two are xlated by algebraic equivalence
8726 during parsing SDCC.y */
8727 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8728 "got '>=' or '<=' shouldn't have come here");
8732 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8744 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8748 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8752 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8779 case GET_VALUE_AT_ADDRESS:
8780 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8784 if (POINTER_SET (ic))
8785 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8811 addSet (&_G.sendSet, ic);
8815 gen51AggregateAssign(ic);
8824 /* now we are ready to call the
8825 peep hole optimizer */
8826 if (!options.nopeep)
8827 peepHole (&lineHead);
8829 /* now do the actual printing */
8830 printLine (lineHead, codeOutFile);