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)
1448 for (ic = lic; ic; ic = ic->next)
1449 if (ic->op == CALL || ic->op == PCALL)
1454 fprintf (stderr, "found parameter push with no function call\n");
1458 /* if the registers have been saved already or don't need to be then
1460 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1461 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1464 /* find the registers in use at this time
1465 and push them away to safety */
1466 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1470 if (options.useXstack)
1472 if (bitVectBitValue (rsave, R0_IDX))
1473 emitcode ("mov", "b,r0");
1474 emitcode ("mov", "r0,%s", spname);
1475 for (i = 0; i < mcs51_nRegs; i++)
1477 if (bitVectBitValue (rsave, i))
1480 emitcode ("mov", "a,b");
1482 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1483 emitcode ("movx", "@r0,a");
1484 emitcode ("inc", "r0");
1487 emitcode ("mov", "%s,r0", spname);
1488 if (bitVectBitValue (rsave, R0_IDX))
1489 emitcode ("mov", "r0,b");
1492 for (i = 0; i < mcs51_nRegs; i++)
1494 if (bitVectBitValue (rsave, i))
1495 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1498 detype = getSpec (operandType (IC_LEFT (ic)));
1501 /*-----------------------------------------------------------------*/
1502 /* unsaveRegisters - pop the pushed registers */
1503 /*-----------------------------------------------------------------*/
1505 unsaveRegisters (iCode * ic)
1509 /* find the registers in use at this time
1510 and push them away to safety */
1511 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1514 if (options.useXstack)
1516 emitcode ("mov", "r0,%s", spname);
1517 for (i = mcs51_nRegs; i >= 0; i--)
1519 if (bitVectBitValue (rsave, i))
1521 emitcode ("dec", "r0");
1522 emitcode ("movx", "a,@r0");
1524 emitcode ("mov", "b,a");
1526 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1530 emitcode ("mov", "%s,r0", spname);
1531 if (bitVectBitValue (rsave, R0_IDX))
1532 emitcode ("mov", "r0,b");
1535 for (i = mcs51_nRegs; i >= 0; i--)
1537 if (bitVectBitValue (rsave, i))
1538 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1544 /*-----------------------------------------------------------------*/
1546 /*-----------------------------------------------------------------*/
1548 pushSide (operand * oper, int size)
1553 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1554 if (AOP_TYPE (oper) != AOP_REG &&
1555 AOP_TYPE (oper) != AOP_DIR &&
1558 emitcode ("mov", "a,%s", l);
1559 emitcode ("push", "acc");
1562 emitcode ("push", "%s", l);
1566 /*-----------------------------------------------------------------*/
1567 /* assignResultValue - */
1568 /*-----------------------------------------------------------------*/
1570 assignResultValue (operand * oper)
1573 int size = AOP_SIZE (oper);
1576 aopPut (AOP (oper), fReturn[offset], offset);
1582 /*-----------------------------------------------------------------*/
1583 /* genXpush - pushes onto the external stack */
1584 /*-----------------------------------------------------------------*/
1586 genXpush (iCode * ic)
1588 asmop *aop = newAsmop (0);
1590 int size, offset = 0;
1592 aopOp (IC_LEFT (ic), ic, FALSE);
1593 r = getFreePtr (ic, &aop, FALSE);
1596 emitcode ("mov", "%s,_spx", r->name);
1598 size = AOP_SIZE (IC_LEFT (ic));
1602 char *l = aopGet (AOP (IC_LEFT (ic)),
1603 offset++, FALSE, FALSE);
1605 emitcode ("movx", "@%s,a", r->name);
1606 emitcode ("inc", "%s", r->name);
1611 emitcode ("mov", "_spx,%s", r->name);
1613 freeAsmop (NULL, aop, ic, TRUE);
1614 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1617 /*-----------------------------------------------------------------*/
1618 /* genIpush - genrate code for pushing this gets a little complex */
1619 /*-----------------------------------------------------------------*/
1621 genIpush (iCode * ic)
1623 int size, offset = 0;
1626 D(emitcode (";", "genIpush"));
1628 /* if this is not a parm push : ie. it is spill push
1629 and spill push is always done on the local stack */
1633 /* and the item is spilt then do nothing */
1634 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1637 aopOp (IC_LEFT (ic), ic, FALSE);
1638 size = AOP_SIZE (IC_LEFT (ic));
1639 /* push it on the stack */
1642 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1648 emitcode ("push", "%s", l);
1653 /* this is a paramter push: in this case we call
1654 the routine to find the call and save those
1655 registers that need to be saved */
1658 /* if use external stack then call the external
1659 stack pushing routine */
1660 if (options.useXstack)
1666 /* then do the push */
1667 aopOp (IC_LEFT (ic), ic, FALSE);
1670 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1671 size = AOP_SIZE (IC_LEFT (ic));
1675 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1676 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1677 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1680 emitcode ("mov", "a,%s", l);
1681 emitcode ("push", "acc");
1684 emitcode ("push", "%s", l);
1687 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1690 /*-----------------------------------------------------------------*/
1691 /* genIpop - recover the registers: can happen only for spilling */
1692 /*-----------------------------------------------------------------*/
1694 genIpop (iCode * ic)
1699 /* if the temp was not pushed then */
1700 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1703 aopOp (IC_LEFT (ic), ic, FALSE);
1704 size = AOP_SIZE (IC_LEFT (ic));
1705 offset = (size - 1);
1707 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1710 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1713 /*-----------------------------------------------------------------*/
1714 /* unsaveRBank - restores the resgister bank from stack */
1715 /*-----------------------------------------------------------------*/
1717 unsaveRBank (int bank, iCode * ic, bool popPsw)
1723 if (options.useXstack)
1727 /* Assume r0 is available for use. */
1728 r = mcs51_regWithIdx (R0_IDX);;
1733 r = getFreePtr (ic, &aop, FALSE);
1735 emitcode ("mov", "%s,_spx", r->name);
1740 if (options.useXstack)
1742 emitcode ("movx", "a,@%s", r->name);
1743 emitcode ("mov", "psw,a");
1744 emitcode ("dec", "%s", r->name);
1748 emitcode ("pop", "psw");
1752 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1754 if (options.useXstack)
1756 emitcode ("movx", "a,@%s", r->name);
1757 emitcode ("mov", "(%s+%d),a",
1758 regs8051[i].base, 8 * bank + regs8051[i].offset);
1759 emitcode ("dec", "%s", r->name);
1763 emitcode ("pop", "(%s+%d)",
1764 regs8051[i].base, 8 * bank + regs8051[i].offset);
1767 if (options.useXstack)
1769 emitcode ("mov", "_spx,%s", r->name);
1774 freeAsmop (NULL, aop, ic, TRUE);
1778 /*-----------------------------------------------------------------*/
1779 /* saveRBank - saves an entire register bank on the stack */
1780 /*-----------------------------------------------------------------*/
1782 saveRBank (int bank, iCode * ic, bool pushPsw)
1788 if (options.useXstack)
1792 /* Assume r0 is available for use. */
1793 r = mcs51_regWithIdx (R0_IDX);;
1798 r = getFreePtr (ic, &aop, FALSE);
1800 emitcode ("mov", "%s,_spx", r->name);
1803 for (i = 0; i < mcs51_nRegs; i++)
1805 if (options.useXstack)
1807 emitcode ("inc", "%s", r->name);
1808 emitcode ("mov", "a,(%s+%d)",
1809 regs8051[i].base, 8 * bank + regs8051[i].offset);
1810 emitcode ("movx", "@%s,a", r->name);
1813 emitcode ("push", "(%s+%d)",
1814 regs8051[i].base, 8 * bank + regs8051[i].offset);
1819 if (options.useXstack)
1821 emitcode ("mov", "a,psw");
1822 emitcode ("movx", "@%s,a", r->name);
1823 emitcode ("inc", "%s", r->name);
1824 emitcode ("mov", "_spx,%s", r->name);
1829 emitcode ("push", "psw");
1832 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1837 freeAsmop (NULL, aop, ic, TRUE);
1846 /*-----------------------------------------------------------------*/
1847 /* genCall - generates a call statement */
1848 /*-----------------------------------------------------------------*/
1850 genCall (iCode * ic)
1853 bool restoreBank = FALSE;
1854 bool swapBanks = FALSE;
1856 D(emitcode(";", "genCall"));
1857 /* if send set is not empty the assign */
1862 for (sic = setFirstItem (_G.sendSet); sic;
1863 sic = setNextItem (_G.sendSet))
1865 int size, offset = 0;
1866 aopOp (IC_LEFT (sic), sic, FALSE);
1867 size = AOP_SIZE (IC_LEFT (sic));
1870 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1872 if (strcmp (l, fReturn[offset]))
1873 emitcode ("mov", "%s,%s",
1878 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1883 /* if we are calling a not _naked function that is not using
1884 the same register bank then we need to save the
1885 destination registers on the stack */
1886 detype = getSpec (operandType (IC_LEFT (ic)));
1887 if (detype && !SPEC_NAKED(detype) &&
1888 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1889 IS_ISR (currFunc->etype))
1893 /* This is unexpected; the bank should have been saved in
1896 saveRBank (SPEC_BANK (detype), ic, FALSE);
1902 /* if caller saves & we have not saved then */
1908 emitcode ("mov", "psw,#0x%02x",
1909 ((SPEC_BANK(detype)) << 3) & 0xff);
1913 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1914 OP_SYMBOL (IC_LEFT (ic))->rname :
1915 OP_SYMBOL (IC_LEFT (ic))->name));
1919 emitcode ("mov", "psw,#0x%02x",
1920 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1923 /* if we need assign a result value */
1924 if ((IS_ITEMP (IC_RESULT (ic)) &&
1925 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1926 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1927 IS_TRUE_SYMOP (IC_RESULT (ic)))
1931 aopOp (IC_RESULT (ic), ic, FALSE);
1934 assignResultValue (IC_RESULT (ic));
1936 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1939 /* adjust the stack for parameters if
1944 if (ic->parmBytes > 3)
1946 emitcode ("mov", "a,%s", spname);
1947 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1948 emitcode ("mov", "%s,a", spname);
1951 for (i = 0; i < ic->parmBytes; i++)
1952 emitcode ("dec", "%s", spname);
1955 /* if we hade saved some registers then unsave them */
1956 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1957 unsaveRegisters (ic);
1959 /* if register bank was saved then pop them */
1961 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1964 /*-----------------------------------------------------------------*/
1965 /* genPcall - generates a call by pointer statement */
1966 /*-----------------------------------------------------------------*/
1968 genPcall (iCode * ic)
1971 symbol *rlbl = newiTempLabel (NULL);
1974 /* if caller saves & we have not saved then */
1978 /* if we are calling a function that is not using
1979 the same register bank then we need to save the
1980 destination registers on the stack */
1981 detype = getSpec (operandType (IC_LEFT (ic)));
1983 IS_ISR (currFunc->etype) &&
1984 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1985 saveRBank (SPEC_BANK (detype), ic, TRUE);
1988 /* push the return address on to the stack */
1989 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1990 emitcode ("push", "acc");
1991 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1992 emitcode ("push", "acc");
1994 /* now push the calling address */
1995 aopOp (IC_LEFT (ic), ic, FALSE);
1997 pushSide (IC_LEFT (ic), FPTRSIZE);
1999 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2001 /* if send set is not empty the assign */
2006 for (sic = setFirstItem (_G.sendSet); sic;
2007 sic = setNextItem (_G.sendSet))
2009 int size, offset = 0;
2010 aopOp (IC_LEFT (sic), sic, FALSE);
2011 size = AOP_SIZE (IC_LEFT (sic));
2014 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2016 if (strcmp (l, fReturn[offset]))
2017 emitcode ("mov", "%s,%s",
2022 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2027 emitcode ("ret", "");
2028 emitcode ("", "%05d$:", (rlbl->key + 100));
2031 /* if we need assign a result value */
2032 if ((IS_ITEMP (IC_RESULT (ic)) &&
2033 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2034 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2035 IS_TRUE_SYMOP (IC_RESULT (ic)))
2039 aopOp (IC_RESULT (ic), ic, FALSE);
2042 assignResultValue (IC_RESULT (ic));
2044 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2047 /* adjust the stack for parameters if
2052 if (ic->parmBytes > 3)
2054 emitcode ("mov", "a,%s", spname);
2055 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2056 emitcode ("mov", "%s,a", spname);
2059 for (i = 0; i < ic->parmBytes; i++)
2060 emitcode ("dec", "%s", spname);
2064 /* if register bank was saved then unsave them */
2066 (SPEC_BANK (currFunc->etype) !=
2067 SPEC_BANK (detype)))
2068 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2070 /* if we hade saved some registers then
2073 unsaveRegisters (ic);
2077 /*-----------------------------------------------------------------*/
2078 /* resultRemat - result is rematerializable */
2079 /*-----------------------------------------------------------------*/
2081 resultRemat (iCode * ic)
2083 if (SKIP_IC (ic) || ic->op == IFX)
2086 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2088 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2089 if (sym->remat && !POINTER_SET (ic))
2096 #if defined(__BORLANDC__) || defined(_MSC_VER)
2097 #define STRCASECMP stricmp
2099 #define STRCASECMP strcasecmp
2102 /*-----------------------------------------------------------------*/
2103 /* inExcludeList - return 1 if the string is in exclude Reg list */
2104 /*-----------------------------------------------------------------*/
2106 inExcludeList (char *s)
2110 if (options.excludeRegs[i] &&
2111 STRCASECMP (options.excludeRegs[i], "none") == 0)
2114 for (i = 0; options.excludeRegs[i]; i++)
2116 if (options.excludeRegs[i] &&
2117 STRCASECMP (s, options.excludeRegs[i]) == 0)
2123 /*-----------------------------------------------------------------*/
2124 /* genFunction - generated code for function entry */
2125 /*-----------------------------------------------------------------*/
2127 genFunction (iCode * ic)
2131 bool switchedPSW = FALSE;
2134 /* create the function header */
2135 emitcode (";", "-----------------------------------------");
2136 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2137 emitcode (";", "-----------------------------------------");
2139 emitcode ("", "%s:", sym->rname);
2140 fetype = getSpec (operandType (IC_LEFT (ic)));
2142 if (SPEC_NAKED(fetype))
2144 emitcode(";", "naked function: no prologue.");
2148 /* if critical function then turn interrupts off */
2149 if (SPEC_CRTCL (fetype))
2150 emitcode ("clr", "ea");
2152 /* here we need to generate the equates for the
2153 register bank if required */
2154 if (SPEC_BANK (fetype) != rbank)
2158 rbank = SPEC_BANK (fetype);
2159 for (i = 0; i < mcs51_nRegs; i++)
2161 if (strcmp (regs8051[i].base, "0") == 0)
2162 emitcode ("", "%s = 0x%02x",
2164 8 * rbank + regs8051[i].offset);
2166 emitcode ("", "%s = %s + 0x%02x",
2169 8 * rbank + regs8051[i].offset);
2173 /* if this is an interrupt service routine then
2174 save acc, b, dpl, dph */
2175 if (IS_ISR (sym->etype))
2178 if (!inExcludeList ("acc"))
2179 emitcode ("push", "acc");
2180 if (!inExcludeList ("b"))
2181 emitcode ("push", "b");
2182 if (!inExcludeList ("dpl"))
2183 emitcode ("push", "dpl");
2184 if (!inExcludeList ("dph"))
2185 emitcode ("push", "dph");
2186 /* if this isr has no bank i.e. is going to
2187 run with bank 0 , then we need to save more
2189 if (!SPEC_BANK (sym->etype))
2192 /* if this function does not call any other
2193 function then we can be economical and
2194 save only those registers that are used */
2199 /* if any registers used */
2202 /* save the registers used */
2203 for (i = 0; i < sym->regsUsed->size; i++)
2205 if (bitVectBitValue (sym->regsUsed, i) ||
2206 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2207 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2214 /* this function has a function call cannot
2215 determines register usage so we will have to push the
2217 saveRBank (0, ic, FALSE);
2222 /* This ISR uses a non-zero bank.
2224 * We assume that the bank is available for our
2227 * However, if this ISR calls a function which uses some
2228 * other bank, we must save that bank entirely.
2230 unsigned long banksToSave = 0;
2235 #define MAX_REGISTER_BANKS 4
2240 for (i = ic; i; i = i->next)
2242 if (i->op == ENDFUNCTION)
2244 /* we got to the end OK. */
2252 detype = getSpec(operandType (IC_LEFT(i)));
2254 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2256 /* Mark this bank for saving. */
2257 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2259 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2263 banksToSave |= (1 << SPEC_BANK(detype));
2266 /* And note that we don't need to do it in
2274 /* This is a mess; we have no idea what
2275 * register bank the called function might
2278 * The only thing I can think of to do is
2279 * throw a warning and hope.
2281 werror(W_FUNCPTR_IN_USING_ISR);
2285 if (banksToSave && options.useXstack)
2287 /* Since we aren't passing it an ic,
2288 * saveRBank will assume r0 is available to abuse.
2290 * So switch to our (trashable) bank now, so
2291 * the caller's R0 isn't trashed.
2293 emitcode ("push", "psw");
2294 emitcode ("mov", "psw,#0x%02x",
2295 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2299 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2301 if (banksToSave & (1 << ix))
2303 saveRBank(ix, NULL, FALSE);
2307 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2312 /* if callee-save to be used for this function
2313 then save the registers being used in this function */
2314 if (sym->calleeSave)
2318 /* if any registers used */
2321 /* save the registers used */
2322 for (i = 0; i < sym->regsUsed->size; i++)
2324 if (bitVectBitValue (sym->regsUsed, i) ||
2325 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2327 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2335 /* set the register bank to the desired value */
2336 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2339 emitcode ("push", "psw");
2340 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2343 if (IS_RENT (sym->etype) || options.stackAuto)
2346 if (options.useXstack)
2348 emitcode ("mov", "r0,%s", spname);
2349 emitcode ("mov", "a,_bp");
2350 emitcode ("movx", "@r0,a");
2351 emitcode ("inc", "%s", spname);
2355 /* set up the stack */
2356 emitcode ("push", "_bp"); /* save the callers stack */
2358 emitcode ("mov", "_bp,%s", spname);
2361 /* adjust the stack for the function */
2367 werror (W_STACK_OVERFLOW, sym->name);
2369 if (i > 3 && sym->recvSize < 4)
2372 emitcode ("mov", "a,sp");
2373 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2374 emitcode ("mov", "sp,a");
2379 emitcode ("inc", "sp");
2385 emitcode ("mov", "a,_spx");
2386 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2387 emitcode ("mov", "_spx,a");
2392 /*-----------------------------------------------------------------*/
2393 /* genEndFunction - generates epilogue for functions */
2394 /*-----------------------------------------------------------------*/
2396 genEndFunction (iCode * ic)
2398 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2400 if (SPEC_NAKED(sym->etype))
2402 emitcode(";", "naked function: no epilogue.");
2406 if (IS_RENT (sym->etype) || options.stackAuto)
2408 emitcode ("mov", "%s,_bp", spname);
2411 /* if use external stack but some variables were
2412 added to the local stack then decrement the
2414 if (options.useXstack && sym->stack)
2416 emitcode ("mov", "a,sp");
2417 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2418 emitcode ("mov", "sp,a");
2422 if ((IS_RENT (sym->etype) || options.stackAuto))
2424 if (options.useXstack)
2426 emitcode ("mov", "r0,%s", spname);
2427 emitcode ("movx", "a,@r0");
2428 emitcode ("mov", "_bp,a");
2429 emitcode ("dec", "%s", spname);
2433 emitcode ("pop", "_bp");
2437 /* restore the register bank */
2438 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2440 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2441 || !options.useXstack)
2443 /* Special case of ISR using non-zero bank with useXstack
2446 emitcode ("pop", "psw");
2450 if (IS_ISR (sym->etype))
2453 /* now we need to restore the registers */
2454 /* if this isr has no bank i.e. is going to
2455 run with bank 0 , then we need to save more
2457 if (!SPEC_BANK (sym->etype))
2459 /* if this function does not call any other
2460 function then we can be economical and
2461 save only those registers that are used */
2466 /* if any registers used */
2469 /* save the registers used */
2470 for (i = sym->regsUsed->size; i >= 0; i--)
2472 if (bitVectBitValue (sym->regsUsed, i) ||
2473 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2474 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2481 /* this function has a function call cannot
2482 determines register usage so we will have to pop the
2484 unsaveRBank (0, ic, FALSE);
2489 /* This ISR uses a non-zero bank.
2491 * Restore any register banks saved by genFunction
2494 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2497 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2499 if (savedBanks & (1 << ix))
2501 unsaveRBank(ix, NULL, FALSE);
2505 if (options.useXstack)
2507 /* Restore bank AFTER calling unsaveRBank,
2508 * since it can trash r0.
2510 emitcode ("pop", "psw");
2514 if (!inExcludeList ("dph"))
2515 emitcode ("pop", "dph");
2516 if (!inExcludeList ("dpl"))
2517 emitcode ("pop", "dpl");
2518 if (!inExcludeList ("b"))
2519 emitcode ("pop", "b");
2520 if (!inExcludeList ("acc"))
2521 emitcode ("pop", "acc");
2523 if (SPEC_CRTCL (sym->etype))
2524 emitcode ("setb", "ea");
2526 /* if debug then send end of function */
2527 /* if (options.debug && currFunc) */
2528 if (options.debug && currFunc)
2531 emitcode ("", "C$%s$%d$%d$%d ==.",
2532 FileBaseName (ic->filename), currFunc->lastLine,
2533 ic->level, ic->block);
2534 if (IS_STATIC (currFunc->etype))
2535 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2537 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2541 emitcode ("reti", "");
2545 if (SPEC_CRTCL (sym->etype))
2546 emitcode ("setb", "ea");
2548 if (sym->calleeSave)
2552 /* if any registers used */
2555 /* save the registers used */
2556 for (i = sym->regsUsed->size; i >= 0; i--)
2558 if (bitVectBitValue (sym->regsUsed, i) ||
2559 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2560 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2566 /* if debug then send end of function */
2567 if (options.debug && currFunc)
2570 emitcode ("", "C$%s$%d$%d$%d ==.",
2571 FileBaseName (ic->filename), currFunc->lastLine,
2572 ic->level, ic->block);
2573 if (IS_STATIC (currFunc->etype))
2574 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2576 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2580 emitcode ("ret", "");
2585 /*-----------------------------------------------------------------*/
2586 /* genRet - generate code for return statement */
2587 /*-----------------------------------------------------------------*/
2591 int size, offset = 0, pushed = 0;
2593 /* if we have no return value then
2594 just generate the "ret" */
2598 /* we have something to return then
2599 move the return value into place */
2600 aopOp (IC_LEFT (ic), ic, FALSE);
2601 size = AOP_SIZE (IC_LEFT (ic));
2606 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2609 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2611 emitcode ("push", "%s", l);
2616 l = aopGet (AOP (IC_LEFT (ic)), offset,
2618 if (strcmp (fReturn[offset], l))
2619 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2628 if (strcmp (fReturn[pushed], "a"))
2629 emitcode ("pop", fReturn[pushed]);
2631 emitcode ("pop", "acc");
2634 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2637 /* generate a jump to the return label
2638 if the next is not the return statement */
2639 if (!(ic->next && ic->next->op == LABEL &&
2640 IC_LABEL (ic->next) == returnLabel))
2642 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2646 /*-----------------------------------------------------------------*/
2647 /* genLabel - generates a label */
2648 /*-----------------------------------------------------------------*/
2650 genLabel (iCode * ic)
2652 /* special case never generate */
2653 if (IC_LABEL (ic) == entryLabel)
2656 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2659 /*-----------------------------------------------------------------*/
2660 /* genGoto - generates a ljmp */
2661 /*-----------------------------------------------------------------*/
2663 genGoto (iCode * ic)
2665 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2668 /*-----------------------------------------------------------------*/
2669 /* findLabelBackwards: walks back through the iCode chain looking */
2670 /* for the given label. Returns number of iCode instructions */
2671 /* between that label and given ic. */
2672 /* Returns zero if label not found. */
2673 /*-----------------------------------------------------------------*/
2675 findLabelBackwards (iCode * ic, int key)
2684 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2686 /* printf("findLabelBackwards = %d\n", count); */
2694 /*-----------------------------------------------------------------*/
2695 /* genPlusIncr :- does addition with increment if possible */
2696 /*-----------------------------------------------------------------*/
2698 genPlusIncr (iCode * ic)
2700 unsigned int icount;
2701 unsigned int size = getDataSize (IC_RESULT (ic));
2703 /* will try to generate an increment */
2704 /* if the right side is not a literal
2706 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2709 /* if the literal value of the right hand side
2710 is greater than 4 then it is not worth it */
2711 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2714 /* if increment 16 bits in register */
2715 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2723 /* If the next instruction is a goto and the goto target
2724 * is < 10 instructions previous to this, we can generate
2725 * jumps straight to that target.
2727 if (ic->next && ic->next->op == GOTO
2728 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2729 && labelRange <= 10)
2731 emitcode (";", "tail increment optimized");
2732 tlbl = IC_LABEL (ic->next);
2737 tlbl = newiTempLabel (NULL);
2740 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2741 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2742 IS_AOP_PREG (IC_RESULT (ic)))
2743 emitcode ("cjne", "%s,#0x00,%05d$"
2744 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2748 emitcode ("clr", "a");
2749 emitcode ("cjne", "a,%s,%05d$"
2750 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2754 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2757 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2758 IS_AOP_PREG (IC_RESULT (ic)))
2759 emitcode ("cjne", "%s,#0x00,%05d$"
2760 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2763 emitcode ("cjne", "a,%s,%05d$"
2764 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2767 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2771 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2772 IS_AOP_PREG (IC_RESULT (ic)))
2773 emitcode ("cjne", "%s,#0x00,%05d$"
2774 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2778 emitcode ("cjne", "a,%s,%05d$"
2779 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2782 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2787 emitcode ("", "%05d$:", tlbl->key + 100);
2792 /* if the sizes are greater than 1 then we cannot */
2793 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2794 AOP_SIZE (IC_LEFT (ic)) > 1)
2797 /* we can if the aops of the left & result match or
2798 if they are in registers and the registers are the
2800 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2805 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2806 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2807 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2813 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2822 /*-----------------------------------------------------------------*/
2823 /* outBitAcc - output a bit in acc */
2824 /*-----------------------------------------------------------------*/
2826 outBitAcc (operand * result)
2828 symbol *tlbl = newiTempLabel (NULL);
2829 /* if the result is a bit */
2830 if (AOP_TYPE (result) == AOP_CRY)
2832 aopPut (AOP (result), "a", 0);
2836 emitcode ("jz", "%05d$", tlbl->key + 100);
2837 emitcode ("mov", "a,%s", one);
2838 emitcode ("", "%05d$:", tlbl->key + 100);
2843 /*-----------------------------------------------------------------*/
2844 /* genPlusBits - generates code for addition of two bits */
2845 /*-----------------------------------------------------------------*/
2847 genPlusBits (iCode * ic)
2849 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2851 symbol *lbl = newiTempLabel (NULL);
2852 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2853 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2854 emitcode ("cpl", "c");
2855 emitcode ("", "%05d$:", (lbl->key + 100));
2856 outBitC (IC_RESULT (ic));
2860 emitcode ("clr", "a");
2861 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2862 emitcode ("rlc", "a");
2863 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2864 emitcode ("addc", "a,#0x00");
2865 outAcc (IC_RESULT (ic));
2870 /* This is the original version of this code.
2872 * This is being kept around for reference,
2873 * because I am not entirely sure I got it right...
2876 adjustArithmeticResult (iCode * ic)
2878 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2879 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2880 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2881 aopPut (AOP (IC_RESULT (ic)),
2882 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2885 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2886 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2887 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2888 aopPut (AOP (IC_RESULT (ic)),
2889 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2892 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2893 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2894 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2895 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2896 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2899 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2900 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2904 /* This is the pure and virtuous version of this code.
2905 * I'm pretty certain it's right, but not enough to toss the old
2909 adjustArithmeticResult (iCode * ic)
2911 if (opIsGptr (IC_RESULT (ic)) &&
2912 opIsGptr (IC_LEFT (ic)) &&
2913 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2915 aopPut (AOP (IC_RESULT (ic)),
2916 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2920 if (opIsGptr (IC_RESULT (ic)) &&
2921 opIsGptr (IC_RIGHT (ic)) &&
2922 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2924 aopPut (AOP (IC_RESULT (ic)),
2925 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2929 if (opIsGptr (IC_RESULT (ic)) &&
2930 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2931 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2932 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2933 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2936 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2937 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2942 /*-----------------------------------------------------------------*/
2943 /* genPlus - generates code for addition */
2944 /*-----------------------------------------------------------------*/
2946 genPlus (iCode * ic)
2948 int size, offset = 0;
2950 /* special cases :- */
2952 aopOp (IC_LEFT (ic), ic, FALSE);
2953 aopOp (IC_RIGHT (ic), ic, FALSE);
2954 aopOp (IC_RESULT (ic), ic, TRUE);
2956 /* if literal, literal on the right or
2957 if left requires ACC or right is already
2959 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2960 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2961 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2963 operand *t = IC_RIGHT (ic);
2964 IC_RIGHT (ic) = IC_LEFT (ic);
2968 /* if both left & right are in bit
2970 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2971 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2977 /* if left in bit space & right literal */
2978 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2979 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2981 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2982 /* if result in bit space */
2983 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2985 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2986 emitcode ("cpl", "c");
2987 outBitC (IC_RESULT (ic));
2991 size = getDataSize (IC_RESULT (ic));
2994 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2995 emitcode ("addc", "a,#00");
2996 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3002 /* if I can do an increment instead
3003 of add then GOOD for ME */
3004 if (genPlusIncr (ic) == TRUE)
3007 size = getDataSize (IC_RESULT (ic));
3011 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3013 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3015 emitcode ("add", "a,%s",
3016 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3018 emitcode ("addc", "a,%s",
3019 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3023 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3025 emitcode ("add", "a,%s",
3026 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3028 emitcode ("addc", "a,%s",
3029 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3031 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3034 adjustArithmeticResult (ic);
3037 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3038 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3039 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3042 /*-----------------------------------------------------------------*/
3043 /* genMinusDec :- does subtraction with deccrement if possible */
3044 /*-----------------------------------------------------------------*/
3046 genMinusDec (iCode * ic)
3048 unsigned int icount;
3049 unsigned int size = getDataSize (IC_RESULT (ic));
3051 /* will try to generate an increment */
3052 /* if the right side is not a literal
3054 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3057 /* if the literal value of the right hand side
3058 is greater than 4 then it is not worth it */
3059 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3062 /* if decrement 16 bits in register */
3063 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3071 /* If the next instruction is a goto and the goto target
3072 * is <= 10 instructions previous to this, we can generate
3073 * jumps straight to that target.
3075 if (ic->next && ic->next->op == GOTO
3076 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3077 && labelRange <= 10)
3079 emitcode (";", "tail decrement optimized");
3080 tlbl = IC_LABEL (ic->next);
3085 tlbl = newiTempLabel (NULL);
3089 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3090 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3091 IS_AOP_PREG (IC_RESULT (ic)))
3092 emitcode ("cjne", "%s,#0xff,%05d$"
3093 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3097 emitcode ("mov", "a,#0xff");
3098 emitcode ("cjne", "a,%s,%05d$"
3099 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3102 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3105 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3106 IS_AOP_PREG (IC_RESULT (ic)))
3107 emitcode ("cjne", "%s,#0xff,%05d$"
3108 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3112 emitcode ("cjne", "a,%s,%05d$"
3113 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3116 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3120 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3121 IS_AOP_PREG (IC_RESULT (ic)))
3122 emitcode ("cjne", "%s,#0xff,%05d$"
3123 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3127 emitcode ("cjne", "a,%s,%05d$"
3128 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3131 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3135 emitcode ("", "%05d$:", tlbl->key + 100);
3140 /* if the sizes are greater than 1 then we cannot */
3141 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3142 AOP_SIZE (IC_LEFT (ic)) > 1)
3145 /* we can if the aops of the left & result match or
3146 if they are in registers and the registers are the
3148 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3152 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3160 /*-----------------------------------------------------------------*/
3161 /* addSign - complete with sign */
3162 /*-----------------------------------------------------------------*/
3164 addSign (operand * result, int offset, int sign)
3166 int size = (getDataSize (result) - offset);
3171 emitcode ("rlc", "a");
3172 emitcode ("subb", "a,acc");
3174 aopPut (AOP (result), "a", offset++);
3178 aopPut (AOP (result), zero, offset++);
3182 /*-----------------------------------------------------------------*/
3183 /* genMinusBits - generates code for subtraction of two bits */
3184 /*-----------------------------------------------------------------*/
3186 genMinusBits (iCode * ic)
3188 symbol *lbl = newiTempLabel (NULL);
3189 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3191 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3192 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3193 emitcode ("cpl", "c");
3194 emitcode ("", "%05d$:", (lbl->key + 100));
3195 outBitC (IC_RESULT (ic));
3199 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3200 emitcode ("subb", "a,acc");
3201 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3202 emitcode ("inc", "a");
3203 emitcode ("", "%05d$:", (lbl->key + 100));
3204 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3205 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3209 /*-----------------------------------------------------------------*/
3210 /* genMinus - generates code for subtraction */
3211 /*-----------------------------------------------------------------*/
3213 genMinus (iCode * ic)
3215 int size, offset = 0;
3216 unsigned long lit = 0L;
3218 aopOp (IC_LEFT (ic), ic, FALSE);
3219 aopOp (IC_RIGHT (ic), ic, FALSE);
3220 aopOp (IC_RESULT (ic), ic, TRUE);
3222 /* special cases :- */
3223 /* if both left & right are in bit space */
3224 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3225 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3231 /* if I can do an decrement instead
3232 of subtract then GOOD for ME */
3233 if (genMinusDec (ic) == TRUE)
3236 size = getDataSize (IC_RESULT (ic));
3238 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3244 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3248 /* if literal, add a,#-lit, else normal subb */
3251 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3252 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3253 emitcode ("subb", "a,%s",
3254 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3257 /* first add without previous c */
3259 if (!size && lit==-1) {
3260 emitcode ("dec", "a");
3262 emitcode ("add", "a,#0x%02x",
3263 (unsigned int) (lit & 0x0FFL));
3266 emitcode ("addc", "a,#0x%02x",
3267 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3270 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3273 adjustArithmeticResult (ic);
3276 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3277 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3278 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3282 /*-----------------------------------------------------------------*/
3283 /* genMultbits :- multiplication of bits */
3284 /*-----------------------------------------------------------------*/
3286 genMultbits (operand * left,
3290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3291 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3296 /*-----------------------------------------------------------------*/
3297 /* genMultOneByte : 8*8=8/16 bit multiplication */
3298 /*-----------------------------------------------------------------*/
3300 genMultOneByte (operand * left,
3304 sym_link *opetype = operandType (result);
3306 int size=AOP_SIZE(result);
3308 if (size<1 || size>2) {
3309 // this should never happen
3310 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3311 AOP_SIZE(result), __FILE__, lineno);
3315 /* (if two literals: the value is computed before) */
3316 /* if one literal, literal on the right */
3317 if (AOP_TYPE (left) == AOP_LIT)
3322 //emitcode (";", "swapped left and right");
3325 if (SPEC_USIGN(opetype)
3326 // ignore the sign of left and right, what else can we do?
3327 || (SPEC_USIGN(operandType(left)) &&
3328 SPEC_USIGN(operandType(right)))) {
3329 // just an unsigned 8*8=8/16 multiply
3330 //emitcode (";","unsigned");
3331 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3332 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3333 emitcode ("mul", "ab");
3334 aopPut (AOP (result), "a", 0);
3336 aopPut (AOP (result), "b", 1);
3341 // we have to do a signed multiply
3343 //emitcode (";", "signed");
3344 emitcode ("clr", "F0"); // reset sign flag
3345 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3347 lbl=newiTempLabel(NULL);
3348 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3349 // left side is negative, 8-bit two's complement, this fails for -128
3350 emitcode ("setb", "F0"); // set sign flag
3351 emitcode ("cpl", "a");
3352 emitcode ("inc", "a");
3354 emitcode ("", "%05d$:", lbl->key+100);
3357 if (AOP_TYPE(right)==AOP_LIT) {
3358 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3359 /* AND literal negative */
3361 emitcode ("cpl", "F0"); // complement sign flag
3362 emitcode ("mov", "b,#0x%02x", -val);
3364 emitcode ("mov", "b,#0x%02x", val);
3367 lbl=newiTempLabel(NULL);
3368 emitcode ("mov", "b,a");
3369 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3370 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3371 // right side is negative, 8-bit two's complement
3372 emitcode ("cpl", "F0"); // complement sign flag
3373 emitcode ("cpl", "a");
3374 emitcode ("inc", "a");
3375 emitcode ("", "%05d$:", lbl->key+100);
3377 emitcode ("mul", "ab");
3379 lbl=newiTempLabel(NULL);
3380 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3381 // only ONE op was negative, we have to do a 8/16-bit two's complement
3382 emitcode ("cpl", "a"); // lsb
3384 emitcode ("inc", "a");
3386 emitcode ("add", "a,#1");
3387 emitcode ("xch", "a,b");
3388 emitcode ("cpl", "a"); // msb
3389 emitcode ("addc", "a,#0");
3390 emitcode ("xch", "a,b");
3393 emitcode ("", "%05d$:", lbl->key+100);
3394 aopPut (AOP (result), "a", 0);
3396 aopPut (AOP (result), "b", 1);
3400 /*-----------------------------------------------------------------*/
3401 /* genMult - generates code for multiplication */
3402 /*-----------------------------------------------------------------*/
3404 genMult (iCode * ic)
3406 operand *left = IC_LEFT (ic);
3407 operand *right = IC_RIGHT (ic);
3408 operand *result = IC_RESULT (ic);
3410 /* assign the amsops */
3411 aopOp (left, ic, FALSE);
3412 aopOp (right, ic, FALSE);
3413 aopOp (result, ic, TRUE);
3415 /* special cases first */
3417 if (AOP_TYPE (left) == AOP_CRY &&
3418 AOP_TYPE (right) == AOP_CRY)
3420 genMultbits (left, right, result);
3424 /* if both are of size == 1 */
3425 if (AOP_SIZE (left) == 1 &&
3426 AOP_SIZE (right) == 1)
3428 genMultOneByte (left, right, result);
3432 /* should have been converted to function call */
3436 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3438 freeAsmop (result, NULL, ic, TRUE);
3441 /*-----------------------------------------------------------------*/
3442 /* genDivbits :- division of bits */
3443 /*-----------------------------------------------------------------*/
3445 genDivbits (operand * left,
3452 /* the result must be bit */
3453 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3454 l = aopGet (AOP (left), 0, FALSE, FALSE);
3458 emitcode ("div", "ab");
3459 emitcode ("rrc", "a");
3460 aopPut (AOP (result), "c", 0);
3463 /*-----------------------------------------------------------------*/
3464 /* genDivOneByte : 8 bit division */
3465 /*-----------------------------------------------------------------*/
3467 genDivOneByte (operand * left,
3471 sym_link *opetype = operandType (result);
3476 size = AOP_SIZE (result) - 1;
3478 /* signed or unsigned */
3479 if (SPEC_USIGN (opetype))
3481 /* unsigned is easy */
3482 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3483 l = aopGet (AOP (left), 0, FALSE, FALSE);
3485 emitcode ("div", "ab");
3486 aopPut (AOP (result), "a", 0);
3488 aopPut (AOP (result), zero, offset++);
3492 /* signed is a little bit more difficult */
3494 /* save the signs of the operands */
3495 l = aopGet (AOP (left), 0, FALSE, FALSE);
3497 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3498 emitcode ("push", "acc"); /* save it on the stack */
3500 /* now sign adjust for both left & right */
3501 l = aopGet (AOP (right), 0, FALSE, FALSE);
3503 lbl = newiTempLabel (NULL);
3504 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3505 emitcode ("cpl", "a");
3506 emitcode ("inc", "a");
3507 emitcode ("", "%05d$:", (lbl->key + 100));
3508 emitcode ("mov", "b,a");
3510 /* sign adjust left side */
3511 l = aopGet (AOP (left), 0, FALSE, FALSE);
3514 lbl = newiTempLabel (NULL);
3515 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3516 emitcode ("cpl", "a");
3517 emitcode ("inc", "a");
3518 emitcode ("", "%05d$:", (lbl->key + 100));
3520 /* now the division */
3521 emitcode ("div", "ab");
3522 /* we are interested in the lower order
3524 emitcode ("mov", "b,a");
3525 lbl = newiTempLabel (NULL);
3526 emitcode ("pop", "acc");
3527 /* if there was an over flow we don't
3528 adjust the sign of the result */
3529 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3530 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3532 emitcode ("clr", "a");
3533 emitcode ("subb", "a,b");
3534 emitcode ("mov", "b,a");
3535 emitcode ("", "%05d$:", (lbl->key + 100));
3537 /* now we are done */
3538 aopPut (AOP (result), "b", 0);
3541 emitcode ("mov", "c,b.7");
3542 emitcode ("subb", "a,acc");
3545 aopPut (AOP (result), "a", offset++);
3549 /*-----------------------------------------------------------------*/
3550 /* genDiv - generates code for division */
3551 /*-----------------------------------------------------------------*/
3555 operand *left = IC_LEFT (ic);
3556 operand *right = IC_RIGHT (ic);
3557 operand *result = IC_RESULT (ic);
3559 /* assign the amsops */
3560 aopOp (left, ic, FALSE);
3561 aopOp (right, ic, FALSE);
3562 aopOp (result, ic, TRUE);
3564 /* special cases first */
3566 if (AOP_TYPE (left) == AOP_CRY &&
3567 AOP_TYPE (right) == AOP_CRY)
3569 genDivbits (left, right, result);
3573 /* if both are of size == 1 */
3574 if (AOP_SIZE (left) == 1 &&
3575 AOP_SIZE (right) == 1)
3577 genDivOneByte (left, right, result);
3581 /* should have been converted to function call */
3584 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3585 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (result, NULL, ic, TRUE);
3589 /*-----------------------------------------------------------------*/
3590 /* genModbits :- modulus of bits */
3591 /*-----------------------------------------------------------------*/
3593 genModbits (operand * left,
3600 /* the result must be bit */
3601 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3602 l = aopGet (AOP (left), 0, FALSE, FALSE);
3606 emitcode ("div", "ab");
3607 emitcode ("mov", "a,b");
3608 emitcode ("rrc", "a");
3609 aopPut (AOP (result), "c", 0);
3612 /*-----------------------------------------------------------------*/
3613 /* genModOneByte : 8 bit modulus */
3614 /*-----------------------------------------------------------------*/
3616 genModOneByte (operand * left,
3620 sym_link *opetype = operandType (result);
3624 /* signed or unsigned */
3625 if (SPEC_USIGN (opetype))
3627 /* unsigned is easy */
3628 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3629 l = aopGet (AOP (left), 0, FALSE, FALSE);
3631 emitcode ("div", "ab");
3632 aopPut (AOP (result), "b", 0);
3636 /* signed is a little bit more difficult */
3638 /* save the signs of the operands */
3639 l = aopGet (AOP (left), 0, FALSE, FALSE);
3642 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3643 emitcode ("push", "acc"); /* save it on the stack */
3645 /* now sign adjust for both left & right */
3646 l = aopGet (AOP (right), 0, FALSE, FALSE);
3649 lbl = newiTempLabel (NULL);
3650 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3651 emitcode ("cpl", "a");
3652 emitcode ("inc", "a");
3653 emitcode ("", "%05d$:", (lbl->key + 100));
3654 emitcode ("mov", "b,a");
3656 /* sign adjust left side */
3657 l = aopGet (AOP (left), 0, FALSE, FALSE);
3660 lbl = newiTempLabel (NULL);
3661 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3662 emitcode ("cpl", "a");
3663 emitcode ("inc", "a");
3664 emitcode ("", "%05d$:", (lbl->key + 100));
3666 /* now the multiplication */
3667 emitcode ("div", "ab");
3668 /* we are interested in the lower order
3670 lbl = newiTempLabel (NULL);
3671 emitcode ("pop", "acc");
3672 /* if there was an over flow we don't
3673 adjust the sign of the result */
3674 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3675 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3677 emitcode ("clr", "a");
3678 emitcode ("subb", "a,b");
3679 emitcode ("mov", "b,a");
3680 emitcode ("", "%05d$:", (lbl->key + 100));
3682 /* now we are done */
3683 aopPut (AOP (result), "b", 0);
3687 /*-----------------------------------------------------------------*/
3688 /* genMod - generates code for division */
3689 /*-----------------------------------------------------------------*/
3693 operand *left = IC_LEFT (ic);
3694 operand *right = IC_RIGHT (ic);
3695 operand *result = IC_RESULT (ic);
3697 /* assign the amsops */
3698 aopOp (left, ic, FALSE);
3699 aopOp (right, ic, FALSE);
3700 aopOp (result, ic, TRUE);
3702 /* special cases first */
3704 if (AOP_TYPE (left) == AOP_CRY &&
3705 AOP_TYPE (right) == AOP_CRY)
3707 genModbits (left, right, result);
3711 /* if both are of size == 1 */
3712 if (AOP_SIZE (left) == 1 &&
3713 AOP_SIZE (right) == 1)
3715 genModOneByte (left, right, result);
3719 /* should have been converted to function call */
3723 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3724 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3725 freeAsmop (result, NULL, ic, TRUE);
3728 /*-----------------------------------------------------------------*/
3729 /* genIfxJump :- will create a jump depending on the ifx */
3730 /*-----------------------------------------------------------------*/
3732 genIfxJump (iCode * ic, char *jval)
3735 symbol *tlbl = newiTempLabel (NULL);
3738 /* if true label then we jump if condition
3742 jlbl = IC_TRUE (ic);
3743 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3744 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3748 /* false label is present */
3749 jlbl = IC_FALSE (ic);
3750 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3751 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3753 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3754 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3756 emitcode (inst, "%05d$", tlbl->key + 100);
3757 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3758 emitcode ("", "%05d$:", tlbl->key + 100);
3760 /* mark the icode as generated */
3764 /*-----------------------------------------------------------------*/
3765 /* genCmp :- greater or less than comparison */
3766 /*-----------------------------------------------------------------*/
3768 genCmp (operand * left, operand * right,
3769 operand * result, iCode * ifx, int sign, iCode *ic)
3771 int size, offset = 0;
3772 unsigned long lit = 0L;
3774 /* if left & right are bit variables */
3775 if (AOP_TYPE (left) == AOP_CRY &&
3776 AOP_TYPE (right) == AOP_CRY)
3778 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3779 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3783 /* subtract right from left if at the
3784 end the carry flag is set then we know that
3785 left is greater than right */
3786 size = max (AOP_SIZE (left), AOP_SIZE (right));
3788 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3789 if ((size == 1) && !sign &&
3790 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3792 symbol *lbl = newiTempLabel (NULL);
3793 emitcode ("cjne", "%s,%s,%05d$",
3794 aopGet (AOP (left), offset, FALSE, FALSE),
3795 aopGet (AOP (right), offset, FALSE, FALSE),
3797 emitcode ("", "%05d$:", lbl->key + 100);
3801 if (AOP_TYPE (right) == AOP_LIT)
3803 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3804 /* optimize if(x < 0) or if(x >= 0) */
3813 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3814 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3816 genIfxJump (ifx, "acc.7");
3820 emitcode ("rlc", "a");
3828 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3829 if (sign && size == 0)
3831 emitcode ("xrl", "a,#0x80");
3832 if (AOP_TYPE (right) == AOP_LIT)
3834 unsigned long lit = (unsigned long)
3835 floatFromVal (AOP (right)->aopu.aop_lit);
3836 emitcode ("subb", "a,#0x%02x",
3837 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3841 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3842 emitcode ("xrl", "b,#0x80");
3843 emitcode ("subb", "a,b");
3847 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3855 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3861 /* if the result is used in the next
3862 ifx conditional branch then generate
3863 code a little differently */
3865 genIfxJump (ifx, "c");
3868 /* leave the result in acc */
3872 /*-----------------------------------------------------------------*/
3873 /* genCmpGt :- greater than comparison */
3874 /*-----------------------------------------------------------------*/
3876 genCmpGt (iCode * ic, iCode * ifx)
3878 operand *left, *right, *result;
3879 sym_link *letype, *retype;
3882 left = IC_LEFT (ic);
3883 right = IC_RIGHT (ic);
3884 result = IC_RESULT (ic);
3886 letype = getSpec (operandType (left));
3887 retype = getSpec (operandType (right));
3888 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3889 /* assign the amsops */
3890 aopOp (left, ic, FALSE);
3891 aopOp (right, ic, FALSE);
3892 aopOp (result, ic, TRUE);
3894 genCmp (right, left, result, ifx, sign,ic);
3896 freeAsmop (result, NULL, ic, TRUE);
3899 /*-----------------------------------------------------------------*/
3900 /* genCmpLt - less than comparisons */
3901 /*-----------------------------------------------------------------*/
3903 genCmpLt (iCode * ic, iCode * ifx)
3905 operand *left, *right, *result;
3906 sym_link *letype, *retype;
3909 left = IC_LEFT (ic);
3910 right = IC_RIGHT (ic);
3911 result = IC_RESULT (ic);
3913 letype = getSpec (operandType (left));
3914 retype = getSpec (operandType (right));
3915 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3917 /* assign the amsops */
3918 aopOp (left, ic, FALSE);
3919 aopOp (right, ic, FALSE);
3920 aopOp (result, ic, TRUE);
3922 genCmp (left, right, result, ifx, sign,ic);
3924 freeAsmop (result, NULL, ic, TRUE);
3927 /*-----------------------------------------------------------------*/
3928 /* gencjneshort - compare and jump if not equal */
3929 /*-----------------------------------------------------------------*/
3931 gencjneshort (operand * left, operand * right, symbol * lbl)
3933 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3935 unsigned long lit = 0L;
3937 /* if the left side is a literal or
3938 if the right is in a pointer register and left
3940 if ((AOP_TYPE (left) == AOP_LIT) ||
3941 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3947 if (AOP_TYPE (right) == AOP_LIT)
3948 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3950 /* if the right side is a literal then anything goes */
3951 if (AOP_TYPE (right) == AOP_LIT &&
3952 AOP_TYPE (left) != AOP_DIR)
3956 emitcode ("cjne", "%s,%s,%05d$",
3957 aopGet (AOP (left), offset, FALSE, FALSE),
3958 aopGet (AOP (right), offset, FALSE, FALSE),
3964 /* if the right side is in a register or in direct space or
3965 if the left is a pointer register & right is not */
3966 else if (AOP_TYPE (right) == AOP_REG ||
3967 AOP_TYPE (right) == AOP_DIR ||
3968 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3969 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3973 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3974 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3975 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3976 emitcode ("jnz", "%05d$", lbl->key + 100);
3978 emitcode ("cjne", "a,%s,%05d$",
3979 aopGet (AOP (right), offset, FALSE, TRUE),
3986 /* right is a pointer reg need both a & b */
3989 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3990 if (strcmp (l, "b"))
3991 emitcode ("mov", "b,%s", l);
3992 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3993 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3999 /*-----------------------------------------------------------------*/
4000 /* gencjne - compare and jump if not equal */
4001 /*-----------------------------------------------------------------*/
4003 gencjne (operand * left, operand * right, symbol * lbl)
4005 symbol *tlbl = newiTempLabel (NULL);
4007 gencjneshort (left, right, lbl);
4009 emitcode ("mov", "a,%s", one);
4010 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4011 emitcode ("", "%05d$:", lbl->key + 100);
4012 emitcode ("clr", "a");
4013 emitcode ("", "%05d$:", tlbl->key + 100);
4016 /*-----------------------------------------------------------------*/
4017 /* genCmpEq - generates code for equal to */
4018 /*-----------------------------------------------------------------*/
4020 genCmpEq (iCode * ic, iCode * ifx)
4022 operand *left, *right, *result;
4024 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4025 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4026 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4028 /* if literal, literal on the right or
4029 if the right is in a pointer register and left
4031 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4032 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4034 operand *t = IC_RIGHT (ic);
4035 IC_RIGHT (ic) = IC_LEFT (ic);
4039 if (ifx && !AOP_SIZE (result))
4042 /* if they are both bit variables */
4043 if (AOP_TYPE (left) == AOP_CRY &&
4044 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4046 if (AOP_TYPE (right) == AOP_LIT)
4048 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4052 emitcode ("cpl", "c");
4056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4060 emitcode ("clr", "c");
4062 /* AOP_TYPE(right) == AOP_CRY */
4066 symbol *lbl = newiTempLabel (NULL);
4067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4068 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4069 emitcode ("cpl", "c");
4070 emitcode ("", "%05d$:", (lbl->key + 100));
4072 /* if true label then we jump if condition
4074 tlbl = newiTempLabel (NULL);
4077 emitcode ("jnc", "%05d$", tlbl->key + 100);
4078 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4082 emitcode ("jc", "%05d$", tlbl->key + 100);
4083 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4085 emitcode ("", "%05d$:", tlbl->key + 100);
4089 tlbl = newiTempLabel (NULL);
4090 gencjneshort (left, right, tlbl);
4093 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4094 emitcode ("", "%05d$:", tlbl->key + 100);
4098 symbol *lbl = newiTempLabel (NULL);
4099 emitcode ("sjmp", "%05d$", lbl->key + 100);
4100 emitcode ("", "%05d$:", tlbl->key + 100);
4101 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4102 emitcode ("", "%05d$:", lbl->key + 100);
4105 /* mark the icode as generated */
4110 /* if they are both bit variables */
4111 if (AOP_TYPE (left) == AOP_CRY &&
4112 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4114 if (AOP_TYPE (right) == AOP_LIT)
4116 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4119 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4120 emitcode ("cpl", "c");
4124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4128 emitcode ("clr", "c");
4130 /* AOP_TYPE(right) == AOP_CRY */
4134 symbol *lbl = newiTempLabel (NULL);
4135 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4136 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4137 emitcode ("cpl", "c");
4138 emitcode ("", "%05d$:", (lbl->key + 100));
4141 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4148 genIfxJump (ifx, "c");
4151 /* if the result is used in an arithmetic operation
4152 then put the result in place */
4157 gencjne (left, right, newiTempLabel (NULL));
4158 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4160 aopPut (AOP (result), "a", 0);
4165 genIfxJump (ifx, "a");
4168 /* if the result is used in an arithmetic operation
4169 then put the result in place */
4170 if (AOP_TYPE (result) != AOP_CRY)
4172 /* leave the result in acc */
4176 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4177 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178 freeAsmop (result, NULL, ic, TRUE);
4181 /*-----------------------------------------------------------------*/
4182 /* ifxForOp - returns the icode containing the ifx for operand */
4183 /*-----------------------------------------------------------------*/
4185 ifxForOp (operand * op, iCode * ic)
4187 /* if true symbol then needs to be assigned */
4188 if (IS_TRUE_SYMOP (op))
4191 /* if this has register type condition and
4192 the next instruction is ifx with the same operand
4193 and live to of the operand is upto the ifx only then */
4195 ic->next->op == IFX &&
4196 IC_COND (ic->next)->key == op->key &&
4197 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4203 /*-----------------------------------------------------------------*/
4204 /* hasInc - operand is incremented before any other use */
4205 /*-----------------------------------------------------------------*/
4207 hasInc (operand *op, iCode *ic)
4209 sym_link *type = operandType(op);
4210 sym_link *retype = getSpec (type);
4211 iCode *lic = ic->next;
4214 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4215 isize = getSize(type->next);
4217 /* if operand of the form op = op + <sizeof *op> */
4218 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4219 isOperandEqual(IC_RESULT(lic),op) &&
4220 isOperandLiteral(IC_RIGHT(lic)) &&
4221 operandLitValue(IC_RIGHT(lic)) == isize) {
4224 /* if the operand used or deffed */
4225 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4233 /*-----------------------------------------------------------------*/
4234 /* genAndOp - for && operation */
4235 /*-----------------------------------------------------------------*/
4237 genAndOp (iCode * ic)
4239 operand *left, *right, *result;
4242 /* note here that && operations that are in an
4243 if statement are taken away by backPatchLabels
4244 only those used in arthmetic operations remain */
4245 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4246 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4247 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4249 /* if both are bit variables */
4250 if (AOP_TYPE (left) == AOP_CRY &&
4251 AOP_TYPE (right) == AOP_CRY)
4253 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4254 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4259 tlbl = newiTempLabel (NULL);
4261 emitcode ("jz", "%05d$", tlbl->key + 100);
4263 emitcode ("", "%05d$:", tlbl->key + 100);
4267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (result, NULL, ic, TRUE);
4273 /*-----------------------------------------------------------------*/
4274 /* genOrOp - for || operation */
4275 /*-----------------------------------------------------------------*/
4277 genOrOp (iCode * ic)
4279 operand *left, *right, *result;
4282 /* note here that || operations that are in an
4283 if statement are taken away by backPatchLabels
4284 only those used in arthmetic operations remain */
4285 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4286 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4287 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4289 /* if both are bit variables */
4290 if (AOP_TYPE (left) == AOP_CRY &&
4291 AOP_TYPE (right) == AOP_CRY)
4293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4294 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4299 tlbl = newiTempLabel (NULL);
4301 emitcode ("jnz", "%05d$", tlbl->key + 100);
4303 emitcode ("", "%05d$:", tlbl->key + 100);
4307 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4308 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 freeAsmop (result, NULL, ic, TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* isLiteralBit - test if lit == 2^n */
4314 /*-----------------------------------------------------------------*/
4316 isLiteralBit (unsigned long lit)
4318 unsigned long pw[32] =
4319 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4320 0x100L, 0x200L, 0x400L, 0x800L,
4321 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4322 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4323 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4324 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4325 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4328 for (idx = 0; idx < 32; idx++)
4334 /*-----------------------------------------------------------------*/
4335 /* continueIfTrue - */
4336 /*-----------------------------------------------------------------*/
4338 continueIfTrue (iCode * ic)
4341 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4345 /*-----------------------------------------------------------------*/
4347 /*-----------------------------------------------------------------*/
4349 jumpIfTrue (iCode * ic)
4352 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4356 /*-----------------------------------------------------------------*/
4357 /* jmpTrueOrFalse - */
4358 /*-----------------------------------------------------------------*/
4360 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4362 // ugly but optimized by peephole
4365 symbol *nlbl = newiTempLabel (NULL);
4366 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4367 emitcode ("", "%05d$:", tlbl->key + 100);
4368 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4369 emitcode ("", "%05d$:", nlbl->key + 100);
4373 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4374 emitcode ("", "%05d$:", tlbl->key + 100);
4379 /*-----------------------------------------------------------------*/
4380 /* genAnd - code for and */
4381 /*-----------------------------------------------------------------*/
4383 genAnd (iCode * ic, iCode * ifx)
4385 operand *left, *right, *result;
4386 int size, offset = 0;
4387 unsigned long lit = 0L;
4391 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4392 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4393 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4396 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4398 AOP_TYPE (left), AOP_TYPE (right));
4399 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4401 AOP_SIZE (left), AOP_SIZE (right));
4404 /* if left is a literal & right is not then exchange them */
4405 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4406 AOP_NEEDSACC (left))
4408 operand *tmp = right;
4413 /* if result = right then exchange them */
4414 if (sameRegs (AOP (result), AOP (right)))
4416 operand *tmp = right;
4421 /* if right is bit then exchange them */
4422 if (AOP_TYPE (right) == AOP_CRY &&
4423 AOP_TYPE (left) != AOP_CRY)
4425 operand *tmp = right;
4429 if (AOP_TYPE (right) == AOP_LIT)
4430 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4432 size = AOP_SIZE (result);
4435 // result = bit & yy;
4436 if (AOP_TYPE (left) == AOP_CRY)
4438 // c = bit & literal;
4439 if (AOP_TYPE (right) == AOP_LIT)
4443 if (size && sameRegs (AOP (result), AOP (left)))
4446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4451 if (size && (AOP_TYPE (result) == AOP_CRY))
4453 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4456 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4461 emitcode ("clr", "c");
4466 if (AOP_TYPE (right) == AOP_CRY)
4469 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4470 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4475 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4477 emitcode ("rrc", "a");
4478 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4486 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4487 genIfxJump (ifx, "c");
4491 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4492 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4493 if ((AOP_TYPE (right) == AOP_LIT) &&
4494 (AOP_TYPE (result) == AOP_CRY) &&
4495 (AOP_TYPE (left) != AOP_CRY))
4497 int posbit = isLiteralBit (lit);
4502 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4505 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4511 sprintf (buffer, "acc.%d", posbit & 0x07);
4512 genIfxJump (ifx, buffer);
4519 symbol *tlbl = newiTempLabel (NULL);
4520 int sizel = AOP_SIZE (left);
4522 emitcode ("setb", "c");
4525 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4527 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4529 if ((posbit = isLiteralBit (bytelit)) != 0)
4530 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4533 if (bytelit != 0x0FFL)
4534 emitcode ("anl", "a,%s",
4535 aopGet (AOP (right), offset, FALSE, TRUE));
4536 emitcode ("jnz", "%05d$", tlbl->key + 100);
4541 // bit = left & literal
4544 emitcode ("clr", "c");
4545 emitcode ("", "%05d$:", tlbl->key + 100);
4547 // if(left & literal)
4551 jmpTrueOrFalse (ifx, tlbl);
4559 /* if left is same as result */
4560 if (sameRegs (AOP (result), AOP (left)))
4562 for (; size--; offset++)
4564 if (AOP_TYPE (right) == AOP_LIT)
4566 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4568 else if (bytelit == 0)
4569 aopPut (AOP (result), zero, offset);
4570 else if (IS_AOP_PREG (result))
4572 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4573 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4574 aopPut (AOP (result), "a", offset);
4577 emitcode ("anl", "%s,%s",
4578 aopGet (AOP (left), offset, FALSE, TRUE),
4579 aopGet (AOP (right), offset, FALSE, FALSE));
4583 if (AOP_TYPE (left) == AOP_ACC)
4584 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4587 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4588 if (IS_AOP_PREG (result))
4590 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4591 aopPut (AOP (result), "a", offset);
4595 emitcode ("anl", "%s,a",
4596 aopGet (AOP (left), offset, FALSE, TRUE));
4603 // left & result in different registers
4604 if (AOP_TYPE (result) == AOP_CRY)
4607 // if(size), result in bit
4608 // if(!size && ifx), conditional oper: if(left & right)
4609 symbol *tlbl = newiTempLabel (NULL);
4610 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4612 emitcode ("setb", "c");
4615 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4616 emitcode ("anl", "a,%s",
4617 aopGet (AOP (right), offset, FALSE, FALSE));
4619 if (AOP_TYPE(left)==AOP_ACC) {
4620 emitcode("mov", "b,a");
4621 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4622 emitcode("anl", "a,b");
4624 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4625 emitcode ("anl", "a,%s",
4626 aopGet (AOP (left), offset, FALSE, FALSE));
4629 emitcode ("jnz", "%05d$", tlbl->key + 100);
4635 emitcode ("", "%05d$:", tlbl->key + 100);
4639 jmpTrueOrFalse (ifx, tlbl);
4643 for (; (size--); offset++)
4646 // result = left & right
4647 if (AOP_TYPE (right) == AOP_LIT)
4649 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4651 aopPut (AOP (result),
4652 aopGet (AOP (left), offset, FALSE, FALSE),
4656 else if (bytelit == 0)
4658 aopPut (AOP (result), zero, offset);
4662 // faster than result <- left, anl result,right
4663 // and better if result is SFR
4664 if (AOP_TYPE (left) == AOP_ACC)
4665 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4668 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4669 emitcode ("anl", "a,%s",
4670 aopGet (AOP (left), offset, FALSE, FALSE));
4672 aopPut (AOP (result), "a", offset);
4678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (result, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* genOr - code for or */
4685 /*-----------------------------------------------------------------*/
4687 genOr (iCode * ic, iCode * ifx)
4689 operand *left, *right, *result;
4690 int size, offset = 0;
4691 unsigned long lit = 0L;
4693 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4694 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4695 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4698 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4700 AOP_TYPE (left), AOP_TYPE (right));
4701 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4703 AOP_SIZE (left), AOP_SIZE (right));
4706 /* if left is a literal & right is not then exchange them */
4707 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4708 AOP_NEEDSACC (left))
4710 operand *tmp = right;
4715 /* if result = right then exchange them */
4716 if (sameRegs (AOP (result), AOP (right)))
4718 operand *tmp = right;
4723 /* if right is bit then exchange them */
4724 if (AOP_TYPE (right) == AOP_CRY &&
4725 AOP_TYPE (left) != AOP_CRY)
4727 operand *tmp = right;
4731 if (AOP_TYPE (right) == AOP_LIT)
4732 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4734 size = AOP_SIZE (result);
4738 if (AOP_TYPE (left) == AOP_CRY)
4740 if (AOP_TYPE (right) == AOP_LIT)
4742 // c = bit & literal;
4745 // lit != 0 => result = 1
4746 if (AOP_TYPE (result) == AOP_CRY)
4749 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4751 continueIfTrue (ifx);
4754 emitcode ("setb", "c");
4758 // lit == 0 => result = left
4759 if (size && sameRegs (AOP (result), AOP (left)))
4761 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4766 if (AOP_TYPE (right) == AOP_CRY)
4769 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4770 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4775 symbol *tlbl = newiTempLabel (NULL);
4776 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4777 emitcode ("setb", "c");
4778 emitcode ("jb", "%s,%05d$",
4779 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4781 emitcode ("jnz", "%05d$", tlbl->key + 100);
4782 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4784 jmpTrueOrFalse (ifx, tlbl);
4790 emitcode ("", "%05d$:", tlbl->key + 100);
4799 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4800 genIfxJump (ifx, "c");
4804 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4805 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4806 if ((AOP_TYPE (right) == AOP_LIT) &&
4807 (AOP_TYPE (result) == AOP_CRY) &&
4808 (AOP_TYPE (left) != AOP_CRY))
4814 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4816 continueIfTrue (ifx);
4821 // lit = 0, result = boolean(left)
4823 emitcode ("setb", "c");
4827 symbol *tlbl = newiTempLabel (NULL);
4828 emitcode ("jnz", "%05d$", tlbl->key + 100);
4830 emitcode ("", "%05d$:", tlbl->key + 100);
4834 genIfxJump (ifx, "a");
4842 /* if left is same as result */
4843 if (sameRegs (AOP (result), AOP (left)))
4845 for (; size--; offset++)
4847 if (AOP_TYPE (right) == AOP_LIT)
4849 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4851 else if (IS_AOP_PREG (left))
4853 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4854 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4855 aopPut (AOP (result), "a", offset);
4858 emitcode ("orl", "%s,%s",
4859 aopGet (AOP (left), offset, FALSE, TRUE),
4860 aopGet (AOP (right), offset, FALSE, FALSE));
4864 if (AOP_TYPE (left) == AOP_ACC)
4865 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4868 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4869 if (IS_AOP_PREG (left))
4871 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4872 aopPut (AOP (result), "a", offset);
4875 emitcode ("orl", "%s,a",
4876 aopGet (AOP (left), offset, FALSE, TRUE));
4883 // left & result in different registers
4884 if (AOP_TYPE (result) == AOP_CRY)
4887 // if(size), result in bit
4888 // if(!size && ifx), conditional oper: if(left | right)
4889 symbol *tlbl = newiTempLabel (NULL);
4890 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4892 emitcode ("setb", "c");
4895 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4896 emitcode ("orl", "a,%s",
4897 aopGet (AOP (right), offset, FALSE, FALSE));
4899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4900 emitcode ("orl", "a,%s",
4901 aopGet (AOP (left), offset, FALSE, FALSE));
4903 emitcode ("jnz", "%05d$", tlbl->key + 100);
4909 emitcode ("", "%05d$:", tlbl->key + 100);
4913 jmpTrueOrFalse (ifx, tlbl);
4916 for (; (size--); offset++)
4919 // result = left & right
4920 if (AOP_TYPE (right) == AOP_LIT)
4922 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4924 aopPut (AOP (result),
4925 aopGet (AOP (left), offset, FALSE, FALSE),
4930 // faster than result <- left, anl result,right
4931 // and better if result is SFR
4932 if (AOP_TYPE (left) == AOP_ACC)
4933 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4936 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4937 emitcode ("orl", "a,%s",
4938 aopGet (AOP (left), offset, FALSE, FALSE));
4940 aopPut (AOP (result), "a", offset);
4945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947 freeAsmop (result, NULL, ic, TRUE);
4950 /*-----------------------------------------------------------------*/
4951 /* genXor - code for xclusive or */
4952 /*-----------------------------------------------------------------*/
4954 genXor (iCode * ic, iCode * ifx)
4956 operand *left, *right, *result;
4957 int size, offset = 0;
4958 unsigned long lit = 0L;
4960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4965 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4967 AOP_TYPE (left), AOP_TYPE (right));
4968 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4970 AOP_SIZE (left), AOP_SIZE (right));
4973 /* if left is a literal & right is not ||
4974 if left needs acc & right does not */
4975 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4976 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4978 operand *tmp = right;
4983 /* if result = right then exchange them */
4984 if (sameRegs (AOP (result), AOP (right)))
4986 operand *tmp = right;
4991 /* if right is bit then exchange them */
4992 if (AOP_TYPE (right) == AOP_CRY &&
4993 AOP_TYPE (left) != AOP_CRY)
4995 operand *tmp = right;
4999 if (AOP_TYPE (right) == AOP_LIT)
5000 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5002 size = AOP_SIZE (result);
5006 if (AOP_TYPE (left) == AOP_CRY)
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 // c = bit & literal;
5013 // lit>>1 != 0 => result = 1
5014 if (AOP_TYPE (result) == AOP_CRY)
5017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5019 continueIfTrue (ifx);
5022 emitcode ("setb", "c");
5029 // lit == 0, result = left
5030 if (size && sameRegs (AOP (result), AOP (left)))
5032 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5036 // lit == 1, result = not(left)
5037 if (size && sameRegs (AOP (result), AOP (left)))
5039 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5045 emitcode ("cpl", "c");
5054 symbol *tlbl = newiTempLabel (NULL);
5055 if (AOP_TYPE (right) == AOP_CRY)
5058 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5062 int sizer = AOP_SIZE (right);
5064 // if val>>1 != 0, result = 1
5065 emitcode ("setb", "c");
5068 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5070 // test the msb of the lsb
5071 emitcode ("anl", "a,#0xfe");
5072 emitcode ("jnz", "%05d$", tlbl->key + 100);
5076 emitcode ("rrc", "a");
5078 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5079 emitcode ("cpl", "c");
5080 emitcode ("", "%05d$:", (tlbl->key + 100));
5087 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5088 genIfxJump (ifx, "c");
5092 if (sameRegs (AOP (result), AOP (left)))
5094 /* if left is same as result */
5095 for (; size--; offset++)
5097 if (AOP_TYPE (right) == AOP_LIT)
5099 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5101 else if (IS_AOP_PREG (left))
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5104 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5105 aopPut (AOP (result), "a", offset);
5108 emitcode ("xrl", "%s,%s",
5109 aopGet (AOP (left), offset, FALSE, TRUE),
5110 aopGet (AOP (right), offset, FALSE, FALSE));
5114 if (AOP_TYPE (left) == AOP_ACC)
5115 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5119 if (IS_AOP_PREG (left))
5121 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5122 aopPut (AOP (result), "a", offset);
5125 emitcode ("xrl", "%s,a",
5126 aopGet (AOP (left), offset, FALSE, TRUE));
5133 // left & result in different registers
5134 if (AOP_TYPE (result) == AOP_CRY)
5137 // if(size), result in bit
5138 // if(!size && ifx), conditional oper: if(left ^ right)
5139 symbol *tlbl = newiTempLabel (NULL);
5140 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5142 emitcode ("setb", "c");
5145 if ((AOP_TYPE (right) == AOP_LIT) &&
5146 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5148 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5152 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5153 emitcode ("xrl", "a,%s",
5154 aopGet (AOP (right), offset, FALSE, FALSE));
5156 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5157 emitcode ("xrl", "a,%s",
5158 aopGet (AOP (left), offset, FALSE, FALSE));
5161 emitcode ("jnz", "%05d$", tlbl->key + 100);
5167 emitcode ("", "%05d$:", tlbl->key + 100);
5171 jmpTrueOrFalse (ifx, tlbl);
5174 for (; (size--); offset++)
5177 // result = left & right
5178 if (AOP_TYPE (right) == AOP_LIT)
5180 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5182 aopPut (AOP (result),
5183 aopGet (AOP (left), offset, FALSE, FALSE),
5188 // faster than result <- left, anl result,right
5189 // and better if result is SFR
5190 if (AOP_TYPE (left) == AOP_ACC)
5191 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5194 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5195 emitcode ("xrl", "a,%s",
5196 aopGet (AOP (left), offset, FALSE, TRUE));
5198 aopPut (AOP (result), "a", offset);
5203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 freeAsmop (result, NULL, ic, TRUE);
5208 /*-----------------------------------------------------------------*/
5209 /* genInline - write the inline code out */
5210 /*-----------------------------------------------------------------*/
5212 genInline (iCode * ic)
5214 char *buffer, *bp, *bp1;
5216 _G.inLine += (!options.asmpeep);
5218 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5219 strcpy (buffer, IC_INLINE (ic));
5221 /* emit each line as a code */
5246 /* emitcode("",buffer); */
5247 _G.inLine -= (!options.asmpeep);
5250 /*-----------------------------------------------------------------*/
5251 /* genRRC - rotate right with carry */
5252 /*-----------------------------------------------------------------*/
5256 operand *left, *result;
5257 int size, offset = 0;
5260 /* rotate right with carry */
5261 left = IC_LEFT (ic);
5262 result = IC_RESULT (ic);
5263 aopOp (left, ic, FALSE);
5264 aopOp (result, ic, FALSE);
5266 /* move it to the result */
5267 size = AOP_SIZE (result);
5269 if (size == 1) { /* special case for 1 byte */
5270 l = aopGet (AOP (left), offset, FALSE, FALSE);
5272 emitcode ("rr", "a");
5278 l = aopGet (AOP (left), offset, FALSE, FALSE);
5280 emitcode ("rrc", "a");
5281 if (AOP_SIZE (result) > 1)
5282 aopPut (AOP (result), "a", offset--);
5284 /* now we need to put the carry into the
5285 highest order byte of the result */
5286 if (AOP_SIZE (result) > 1)
5288 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5291 emitcode ("mov", "acc.7,c");
5293 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5294 freeAsmop (left, NULL, ic, TRUE);
5295 freeAsmop (result, NULL, ic, TRUE);
5298 /*-----------------------------------------------------------------*/
5299 /* genRLC - generate code for rotate left with carry */
5300 /*-----------------------------------------------------------------*/
5304 operand *left, *result;
5305 int size, offset = 0;
5308 /* rotate right with carry */
5309 left = IC_LEFT (ic);
5310 result = IC_RESULT (ic);
5311 aopOp (left, ic, FALSE);
5312 aopOp (result, ic, FALSE);
5314 /* move it to the result */
5315 size = AOP_SIZE (result);
5319 l = aopGet (AOP (left), offset, FALSE, FALSE);
5321 if (size == 0) { /* special case for 1 byte */
5325 emitcode ("add", "a,acc");
5326 if (AOP_SIZE (result) > 1)
5327 aopPut (AOP (result), "a", offset++);
5330 l = aopGet (AOP (left), offset, FALSE, FALSE);
5332 emitcode ("rlc", "a");
5333 if (AOP_SIZE (result) > 1)
5334 aopPut (AOP (result), "a", offset++);
5337 /* now we need to put the carry into the
5338 highest order byte of the result */
5339 if (AOP_SIZE (result) > 1)
5341 l = aopGet (AOP (result), 0, FALSE, FALSE);
5344 emitcode ("mov", "acc.0,c");
5346 aopPut (AOP (result), "a", 0);
5347 freeAsmop (left, NULL, ic, TRUE);
5348 freeAsmop (result, NULL, ic, TRUE);
5351 /*-----------------------------------------------------------------*/
5352 /* genGetHbit - generates code get highest order bit */
5353 /*-----------------------------------------------------------------*/
5355 genGetHbit (iCode * ic)
5357 operand *left, *result;
5358 left = IC_LEFT (ic);
5359 result = IC_RESULT (ic);
5360 aopOp (left, ic, FALSE);
5361 aopOp (result, ic, FALSE);
5363 /* get the highest order byte into a */
5364 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5365 if (AOP_TYPE (result) == AOP_CRY)
5367 emitcode ("rlc", "a");
5372 emitcode ("rl", "a");
5373 emitcode ("anl", "a,#0x01");
5378 freeAsmop (left, NULL, ic, TRUE);
5379 freeAsmop (result, NULL, ic, TRUE);
5382 /*-----------------------------------------------------------------*/
5383 /* AccRol - rotate left accumulator by known count */
5384 /*-----------------------------------------------------------------*/
5386 AccRol (int shCount)
5388 shCount &= 0x0007; // shCount : 0..7
5395 emitcode ("rl", "a");
5398 emitcode ("rl", "a");
5399 emitcode ("rl", "a");
5402 emitcode ("swap", "a");
5403 emitcode ("rr", "a");
5406 emitcode ("swap", "a");
5409 emitcode ("swap", "a");
5410 emitcode ("rl", "a");
5413 emitcode ("rr", "a");
5414 emitcode ("rr", "a");
5417 emitcode ("rr", "a");
5422 /*-----------------------------------------------------------------*/
5423 /* AccLsh - left shift accumulator by known count */
5424 /*-----------------------------------------------------------------*/
5426 AccLsh (int shCount)
5431 emitcode ("add", "a,acc");
5432 else if (shCount == 2)
5434 emitcode ("add", "a,acc");
5435 emitcode ("add", "a,acc");
5439 /* rotate left accumulator */
5441 /* and kill the lower order bits */
5442 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5447 /*-----------------------------------------------------------------*/
5448 /* AccRsh - right shift accumulator by known count */
5449 /*-----------------------------------------------------------------*/
5451 AccRsh (int shCount)
5458 emitcode ("rrc", "a");
5462 /* rotate right accumulator */
5463 AccRol (8 - shCount);
5464 /* and kill the higher order bits */
5465 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5470 /*-----------------------------------------------------------------*/
5471 /* AccSRsh - signed right shift accumulator by known count */
5472 /*-----------------------------------------------------------------*/
5474 AccSRsh (int shCount)
5481 emitcode ("mov", "c,acc.7");
5482 emitcode ("rrc", "a");
5484 else if (shCount == 2)
5486 emitcode ("mov", "c,acc.7");
5487 emitcode ("rrc", "a");
5488 emitcode ("mov", "c,acc.7");
5489 emitcode ("rrc", "a");
5493 tlbl = newiTempLabel (NULL);
5494 /* rotate right accumulator */
5495 AccRol (8 - shCount);
5496 /* and kill the higher order bits */
5497 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5498 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5499 emitcode ("orl", "a,#0x%02x",
5500 (unsigned char) ~SRMask[shCount]);
5501 emitcode ("", "%05d$:", tlbl->key + 100);
5506 /*-----------------------------------------------------------------*/
5507 /* shiftR1Left2Result - shift right one byte from left to result */
5508 /*-----------------------------------------------------------------*/
5510 shiftR1Left2Result (operand * left, int offl,
5511 operand * result, int offr,
5512 int shCount, int sign)
5514 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5515 /* shift right accumulator */
5520 aopPut (AOP (result), "a", offr);
5523 /*-----------------------------------------------------------------*/
5524 /* shiftL1Left2Result - shift left one byte from left to result */
5525 /*-----------------------------------------------------------------*/
5527 shiftL1Left2Result (operand * left, int offl,
5528 operand * result, int offr, int shCount)
5531 l = aopGet (AOP (left), offl, FALSE, FALSE);
5533 /* shift left accumulator */
5535 aopPut (AOP (result), "a", offr);
5538 /*-----------------------------------------------------------------*/
5539 /* movLeft2Result - move byte from left to result */
5540 /*-----------------------------------------------------------------*/
5542 movLeft2Result (operand * left, int offl,
5543 operand * result, int offr, int sign)
5546 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5548 l = aopGet (AOP (left), offl, FALSE, FALSE);
5550 if (*l == '@' && (IS_AOP_PREG (result)))
5552 emitcode ("mov", "a,%s", l);
5553 aopPut (AOP (result), "a", offr);
5558 aopPut (AOP (result), l, offr);
5561 /* MSB sign in acc.7 ! */
5562 if (getDataSize (left) == offl + 1)
5564 emitcode ("mov", "a,%s", l);
5565 aopPut (AOP (result), "a", offr);
5572 /*-----------------------------------------------------------------*/
5573 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5574 /*-----------------------------------------------------------------*/
5578 emitcode ("rrc", "a");
5579 emitcode ("xch", "a,%s", x);
5580 emitcode ("rrc", "a");
5581 emitcode ("xch", "a,%s", x);
5584 /*-----------------------------------------------------------------*/
5585 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5586 /*-----------------------------------------------------------------*/
5590 emitcode ("xch", "a,%s", x);
5591 emitcode ("rlc", "a");
5592 emitcode ("xch", "a,%s", x);
5593 emitcode ("rlc", "a");
5596 /*-----------------------------------------------------------------*/
5597 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5598 /*-----------------------------------------------------------------*/
5602 emitcode ("xch", "a,%s", x);
5603 emitcode ("add", "a,acc");
5604 emitcode ("xch", "a,%s", x);
5605 emitcode ("rlc", "a");
5608 /*-----------------------------------------------------------------*/
5609 /* AccAXLsh - left shift a:x by known count (0..7) */
5610 /*-----------------------------------------------------------------*/
5612 AccAXLsh (char *x, int shCount)
5627 case 5: // AAAAABBB:CCCCCDDD
5629 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5631 emitcode ("anl", "a,#0x%02x",
5632 SLMask[shCount]); // BBB00000:CCCCCDDD
5634 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5636 AccRol (shCount); // DDDCCCCC:BBB00000
5638 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5640 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5642 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5644 emitcode ("anl", "a,#0x%02x",
5645 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5647 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5649 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5652 case 6: // AAAAAABB:CCCCCCDD
5653 emitcode ("anl", "a,#0x%02x",
5654 SRMask[shCount]); // 000000BB:CCCCCCDD
5655 emitcode ("mov", "c,acc.0"); // c = B
5656 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5658 AccAXRrl1 (x); // BCCCCCCD:D000000B
5659 AccAXRrl1 (x); // BBCCCCCC:DD000000
5661 emitcode("rrc","a");
5662 emitcode("xch","a,%s", x);
5663 emitcode("rrc","a");
5664 emitcode("mov","c,acc.0"); //<< get correct bit
5665 emitcode("xch","a,%s", x);
5667 emitcode("rrc","a");
5668 emitcode("xch","a,%s", x);
5669 emitcode("rrc","a");
5670 emitcode("xch","a,%s", x);
5673 case 7: // a:x <<= 7
5675 emitcode ("anl", "a,#0x%02x",
5676 SRMask[shCount]); // 0000000B:CCCCCCCD
5678 emitcode ("mov", "c,acc.0"); // c = B
5680 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5682 AccAXRrl1 (x); // BCCCCCCC:D0000000
5690 /*-----------------------------------------------------------------*/
5691 /* AccAXRsh - right shift a:x known count (0..7) */
5692 /*-----------------------------------------------------------------*/
5694 AccAXRsh (char *x, int shCount)
5702 AccAXRrl1 (x); // 0->a:x
5707 AccAXRrl1 (x); // 0->a:x
5710 AccAXRrl1 (x); // 0->a:x
5715 case 5: // AAAAABBB:CCCCCDDD = a:x
5717 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5719 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5721 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5723 emitcode ("anl", "a,#0x%02x",
5724 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5726 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5728 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5730 emitcode ("anl", "a,#0x%02x",
5731 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5733 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5735 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5737 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5740 case 6: // AABBBBBB:CCDDDDDD
5742 emitcode ("mov", "c,acc.7");
5743 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5745 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5747 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5749 emitcode ("anl", "a,#0x%02x",
5750 SRMask[shCount]); // 000000AA:BBBBBBCC
5753 case 7: // ABBBBBBB:CDDDDDDD
5755 emitcode ("mov", "c,acc.7"); // c = A
5757 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5759 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5761 emitcode ("anl", "a,#0x%02x",
5762 SRMask[shCount]); // 0000000A:BBBBBBBC
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXRshS - right shift signed a:x known count (0..7) */
5772 /*-----------------------------------------------------------------*/
5774 AccAXRshS (char *x, int shCount)
5782 emitcode ("mov", "c,acc.7");
5783 AccAXRrl1 (x); // s->a:x
5787 emitcode ("mov", "c,acc.7");
5788 AccAXRrl1 (x); // s->a:x
5790 emitcode ("mov", "c,acc.7");
5791 AccAXRrl1 (x); // s->a:x
5796 case 5: // AAAAABBB:CCCCCDDD = a:x
5798 tlbl = newiTempLabel (NULL);
5799 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5801 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5803 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5805 emitcode ("anl", "a,#0x%02x",
5806 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5808 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5810 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5812 emitcode ("anl", "a,#0x%02x",
5813 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5815 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5817 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5819 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5821 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5822 emitcode ("orl", "a,#0x%02x",
5823 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5825 emitcode ("", "%05d$:", tlbl->key + 100);
5826 break; // SSSSAAAA:BBBCCCCC
5828 case 6: // AABBBBBB:CCDDDDDD
5830 tlbl = newiTempLabel (NULL);
5831 emitcode ("mov", "c,acc.7");
5832 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5834 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5836 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5838 emitcode ("anl", "a,#0x%02x",
5839 SRMask[shCount]); // 000000AA:BBBBBBCC
5841 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5842 emitcode ("orl", "a,#0x%02x",
5843 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5845 emitcode ("", "%05d$:", tlbl->key + 100);
5847 case 7: // ABBBBBBB:CDDDDDDD
5849 tlbl = newiTempLabel (NULL);
5850 emitcode ("mov", "c,acc.7"); // c = A
5852 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5854 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5856 emitcode ("anl", "a,#0x%02x",
5857 SRMask[shCount]); // 0000000A:BBBBBBBC
5859 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5860 emitcode ("orl", "a,#0x%02x",
5861 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5863 emitcode ("", "%05d$:", tlbl->key + 100);
5870 /*-----------------------------------------------------------------*/
5871 /* shiftL2Left2Result - shift left two bytes from left to result */
5872 /*-----------------------------------------------------------------*/
5874 shiftL2Left2Result (operand * left, int offl,
5875 operand * result, int offr, int shCount)
5877 if (sameRegs (AOP (result), AOP (left)) &&
5878 ((offl + MSB16) == offr))
5880 /* don't crash result[offr] */
5881 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5882 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5886 movLeft2Result (left, offl, result, offr, 0);
5887 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5889 /* ax << shCount (x = lsb(result)) */
5890 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5891 aopPut (AOP (result), "a", offr + MSB16);
5895 /*-----------------------------------------------------------------*/
5896 /* shiftR2Left2Result - shift right two bytes from left to result */
5897 /*-----------------------------------------------------------------*/
5899 shiftR2Left2Result (operand * left, int offl,
5900 operand * result, int offr,
5901 int shCount, int sign)
5903 if (sameRegs (AOP (result), AOP (left)) &&
5904 ((offl + MSB16) == offr))
5906 /* don't crash result[offr] */
5907 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5908 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5912 movLeft2Result (left, offl, result, offr, 0);
5913 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5915 /* a:x >> shCount (x = lsb(result)) */
5917 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5919 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5920 if (getDataSize (result) > 1)
5921 aopPut (AOP (result), "a", offr + MSB16);
5924 /*-----------------------------------------------------------------*/
5925 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5926 /*-----------------------------------------------------------------*/
5928 shiftLLeftOrResult (operand * left, int offl,
5929 operand * result, int offr, int shCount)
5931 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5932 /* shift left accumulator */
5934 /* or with result */
5935 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5936 /* back to result */
5937 aopPut (AOP (result), "a", offr);
5940 /*-----------------------------------------------------------------*/
5941 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5942 /*-----------------------------------------------------------------*/
5944 shiftRLeftOrResult (operand * left, int offl,
5945 operand * result, int offr, int shCount)
5947 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5948 /* shift right accumulator */
5950 /* or with result */
5951 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5952 /* back to result */
5953 aopPut (AOP (result), "a", offr);
5956 /*-----------------------------------------------------------------*/
5957 /* genlshOne - left shift a one byte quantity by known count */
5958 /*-----------------------------------------------------------------*/
5960 genlshOne (operand * result, operand * left, int shCount)
5962 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5965 /*-----------------------------------------------------------------*/
5966 /* genlshTwo - left shift two bytes by known amount != 0 */
5967 /*-----------------------------------------------------------------*/
5969 genlshTwo (operand * result, operand * left, int shCount)
5973 size = getDataSize (result);
5975 /* if shCount >= 8 */
5983 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5985 movLeft2Result (left, LSB, result, MSB16, 0);
5987 aopPut (AOP (result), zero, LSB);
5990 /* 1 <= shCount <= 7 */
5994 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5996 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6000 /*-----------------------------------------------------------------*/
6001 /* shiftLLong - shift left one long from left to result */
6002 /* offl = LSB or MSB16 */
6003 /*-----------------------------------------------------------------*/
6005 shiftLLong (operand * left, operand * result, int offr)
6008 int size = AOP_SIZE (result);
6010 if (size >= LSB + offr)
6012 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6014 emitcode ("add", "a,acc");
6015 if (sameRegs (AOP (left), AOP (result)) &&
6016 size >= MSB16 + offr && offr != LSB)
6017 emitcode ("xch", "a,%s",
6018 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6020 aopPut (AOP (result), "a", LSB + offr);
6023 if (size >= MSB16 + offr)
6025 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6027 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6030 emitcode ("rlc", "a");
6031 if (sameRegs (AOP (left), AOP (result)) &&
6032 size >= MSB24 + offr && offr != LSB)
6033 emitcode ("xch", "a,%s",
6034 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6036 aopPut (AOP (result), "a", MSB16 + offr);
6039 if (size >= MSB24 + offr)
6041 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6043 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6046 emitcode ("rlc", "a");
6047 if (sameRegs (AOP (left), AOP (result)) &&
6048 size >= MSB32 + offr && offr != LSB)
6049 emitcode ("xch", "a,%s",
6050 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6052 aopPut (AOP (result), "a", MSB24 + offr);
6055 if (size > MSB32 + offr)
6057 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6059 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6062 emitcode ("rlc", "a");
6063 aopPut (AOP (result), "a", MSB32 + offr);
6066 aopPut (AOP (result), zero, LSB);
6069 /*-----------------------------------------------------------------*/
6070 /* genlshFour - shift four byte by a known amount != 0 */
6071 /*-----------------------------------------------------------------*/
6073 genlshFour (operand * result, operand * left, int shCount)
6077 size = AOP_SIZE (result);
6079 /* if shifting more that 3 bytes */
6084 /* lowest order of left goes to the highest
6085 order of the destination */
6086 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6088 movLeft2Result (left, LSB, result, MSB32, 0);
6089 aopPut (AOP (result), zero, LSB);
6090 aopPut (AOP (result), zero, MSB16);
6091 aopPut (AOP (result), zero, MSB24);
6095 /* more than two bytes */
6096 else if (shCount >= 16)
6098 /* lower order two bytes goes to higher order two bytes */
6100 /* if some more remaining */
6102 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6105 movLeft2Result (left, MSB16, result, MSB32, 0);
6106 movLeft2Result (left, LSB, result, MSB24, 0);
6108 aopPut (AOP (result), zero, MSB16);
6109 aopPut (AOP (result), zero, LSB);
6113 /* if more than 1 byte */
6114 else if (shCount >= 8)
6116 /* lower order three bytes goes to higher order three bytes */
6121 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6123 movLeft2Result (left, LSB, result, MSB16, 0);
6129 movLeft2Result (left, MSB24, result, MSB32, 0);
6130 movLeft2Result (left, MSB16, result, MSB24, 0);
6131 movLeft2Result (left, LSB, result, MSB16, 0);
6132 aopPut (AOP (result), zero, LSB);
6134 else if (shCount == 1)
6135 shiftLLong (left, result, MSB16);
6138 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6139 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6140 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6141 aopPut (AOP (result), zero, LSB);
6146 /* 1 <= shCount <= 7 */
6147 else if (shCount <= 2)
6149 shiftLLong (left, result, LSB);
6151 shiftLLong (result, result, LSB);
6153 /* 3 <= shCount <= 7, optimize */
6156 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6157 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6158 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6162 /*-----------------------------------------------------------------*/
6163 /* genLeftShiftLiteral - left shifting by known count */
6164 /*-----------------------------------------------------------------*/
6166 genLeftShiftLiteral (operand * left,
6171 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6174 freeAsmop (right, NULL, ic, TRUE);
6176 aopOp (left, ic, FALSE);
6177 aopOp (result, ic, FALSE);
6179 size = getSize (operandType (result));
6182 emitcode ("; shift left ", "result %d, left %d", size,
6186 /* I suppose that the left size >= result size */
6191 movLeft2Result (left, size, result, size, 0);
6195 else if (shCount >= (size * 8))
6197 aopPut (AOP (result), zero, size);
6203 genlshOne (result, left, shCount);
6207 genlshTwo (result, left, shCount);
6211 genlshFour (result, left, shCount);
6214 fprintf(stderr, "*** ack! mystery literal shift!\n");
6218 freeAsmop (left, NULL, ic, TRUE);
6219 freeAsmop (result, NULL, ic, TRUE);
6222 /*-----------------------------------------------------------------*/
6223 /* genLeftShift - generates code for left shifting */
6224 /*-----------------------------------------------------------------*/
6226 genLeftShift (iCode * ic)
6228 operand *left, *right, *result;
6231 symbol *tlbl, *tlbl1;
6233 right = IC_RIGHT (ic);
6234 left = IC_LEFT (ic);
6235 result = IC_RESULT (ic);
6237 aopOp (right, ic, FALSE);
6239 /* if the shift count is known then do it
6240 as efficiently as possible */
6241 if (AOP_TYPE (right) == AOP_LIT)
6243 genLeftShiftLiteral (left, right, result, ic);
6247 /* shift count is unknown then we have to form
6248 a loop get the loop count in B : Note: we take
6249 only the lower order byte since shifting
6250 more that 32 bits make no sense anyway, ( the
6251 largest size of an object can be only 32 bits ) */
6253 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6254 emitcode ("inc", "b");
6255 freeAsmop (right, NULL, ic, TRUE);
6256 aopOp (left, ic, FALSE);
6257 aopOp (result, ic, FALSE);
6259 /* now move the left to the result if they are not the
6261 if (!sameRegs (AOP (left), AOP (result)) &&
6262 AOP_SIZE (result) > 1)
6265 size = AOP_SIZE (result);
6269 l = aopGet (AOP (left), offset, FALSE, TRUE);
6270 if (*l == '@' && (IS_AOP_PREG (result)))
6273 emitcode ("mov", "a,%s", l);
6274 aopPut (AOP (result), "a", offset);
6277 aopPut (AOP (result), l, offset);
6282 tlbl = newiTempLabel (NULL);
6283 size = AOP_SIZE (result);
6285 tlbl1 = newiTempLabel (NULL);
6287 /* if it is only one byte then */
6290 symbol *tlbl1 = newiTempLabel (NULL);
6292 l = aopGet (AOP (left), 0, FALSE, FALSE);
6294 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6295 emitcode ("", "%05d$:", tlbl->key + 100);
6296 emitcode ("add", "a,acc");
6297 emitcode ("", "%05d$:", tlbl1->key + 100);
6298 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6299 aopPut (AOP (result), "a", 0);
6303 reAdjustPreg (AOP (result));
6305 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6306 emitcode ("", "%05d$:", tlbl->key + 100);
6307 l = aopGet (AOP (result), offset, FALSE, FALSE);
6309 emitcode ("add", "a,acc");
6310 aopPut (AOP (result), "a", offset++);
6313 l = aopGet (AOP (result), offset, FALSE, FALSE);
6315 emitcode ("rlc", "a");
6316 aopPut (AOP (result), "a", offset++);
6318 reAdjustPreg (AOP (result));
6320 emitcode ("", "%05d$:", tlbl1->key + 100);
6321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6323 freeAsmop (left, NULL, ic, TRUE);
6324 freeAsmop (result, NULL, ic, TRUE);
6327 /*-----------------------------------------------------------------*/
6328 /* genrshOne - right shift a one byte quantity by known count */
6329 /*-----------------------------------------------------------------*/
6331 genrshOne (operand * result, operand * left,
6332 int shCount, int sign)
6334 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6337 /*-----------------------------------------------------------------*/
6338 /* genrshTwo - right shift two bytes by known amount != 0 */
6339 /*-----------------------------------------------------------------*/
6341 genrshTwo (operand * result, operand * left,
6342 int shCount, int sign)
6344 /* if shCount >= 8 */
6349 shiftR1Left2Result (left, MSB16, result, LSB,
6352 movLeft2Result (left, MSB16, result, LSB, sign);
6353 addSign (result, MSB16, sign);
6356 /* 1 <= shCount <= 7 */
6358 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6361 /*-----------------------------------------------------------------*/
6362 /* shiftRLong - shift right one long from left to result */
6363 /* offl = LSB or MSB16 */
6364 /*-----------------------------------------------------------------*/
6366 shiftRLong (operand * left, int offl,
6367 operand * result, int sign)
6369 int isSameRegs=sameRegs(AOP(left),AOP(result));
6371 if (isSameRegs && offl>1) {
6372 // we are in big trouble, but this shouldn't happen
6373 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6376 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6381 emitcode ("rlc", "a");
6382 emitcode ("subb", "a,acc");
6383 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6385 aopPut (AOP(result), zero, MSB32);
6390 emitcode ("clr", "c");
6392 emitcode ("mov", "c,acc.7");
6395 emitcode ("rrc", "a");
6397 if (isSameRegs && offl==MSB16) {
6398 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6400 aopPut (AOP (result), "a", MSB32);
6401 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6404 emitcode ("rrc", "a");
6405 if (isSameRegs && offl==1) {
6406 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6408 aopPut (AOP (result), "a", MSB24);
6409 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6411 emitcode ("rrc", "a");
6412 aopPut (AOP (result), "a", MSB16 - offl);
6416 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6417 emitcode ("rrc", "a");
6418 aopPut (AOP (result), "a", LSB);
6422 /*-----------------------------------------------------------------*/
6423 /* genrshFour - shift four byte by a known amount != 0 */
6424 /*-----------------------------------------------------------------*/
6426 genrshFour (operand * result, operand * left,
6427 int shCount, int sign)
6429 /* if shifting more that 3 bytes */
6434 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6436 movLeft2Result (left, MSB32, result, LSB, sign);
6437 addSign (result, MSB16, sign);
6439 else if (shCount >= 16)
6443 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6446 movLeft2Result (left, MSB24, result, LSB, 0);
6447 movLeft2Result (left, MSB32, result, MSB16, sign);
6449 addSign (result, MSB24, sign);
6451 else if (shCount >= 8)
6455 shiftRLong (left, MSB16, result, sign);
6456 else if (shCount == 0)
6458 movLeft2Result (left, MSB16, result, LSB, 0);
6459 movLeft2Result (left, MSB24, result, MSB16, 0);
6460 movLeft2Result (left, MSB32, result, MSB24, sign);
6461 addSign (result, MSB32, sign);
6465 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6466 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6467 /* the last shift is signed */
6468 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6469 addSign (result, MSB32, sign);
6473 { /* 1 <= shCount <= 7 */
6476 shiftRLong (left, LSB, result, sign);
6478 shiftRLong (result, LSB, result, sign);
6482 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6483 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6484 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6489 /*-----------------------------------------------------------------*/
6490 /* genRightShiftLiteral - right shifting by known count */
6491 /*-----------------------------------------------------------------*/
6493 genRightShiftLiteral (operand * left,
6499 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6502 freeAsmop (right, NULL, ic, TRUE);
6504 aopOp (left, ic, FALSE);
6505 aopOp (result, ic, FALSE);
6508 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6512 size = getDataSize (left);
6513 /* test the LEFT size !!! */
6515 /* I suppose that the left size >= result size */
6518 size = getDataSize (result);
6520 movLeft2Result (left, size, result, size, 0);
6523 else if (shCount >= (size * 8))
6526 /* get sign in acc.7 */
6527 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6528 addSign (result, LSB, sign);
6535 genrshOne (result, left, shCount, sign);
6539 genrshTwo (result, left, shCount, sign);
6543 genrshFour (result, left, shCount, sign);
6549 freeAsmop (left, NULL, ic, TRUE);
6550 freeAsmop (result, NULL, ic, TRUE);
6554 /*-----------------------------------------------------------------*/
6555 /* genSignedRightShift - right shift of signed number */
6556 /*-----------------------------------------------------------------*/
6558 genSignedRightShift (iCode * ic)
6560 operand *right, *left, *result;
6563 symbol *tlbl, *tlbl1;
6565 /* we do it the hard way put the shift count in b
6566 and loop thru preserving the sign */
6568 right = IC_RIGHT (ic);
6569 left = IC_LEFT (ic);
6570 result = IC_RESULT (ic);
6572 aopOp (right, ic, FALSE);
6575 if (AOP_TYPE (right) == AOP_LIT)
6577 genRightShiftLiteral (left, right, result, ic, 1);
6580 /* shift count is unknown then we have to form
6581 a loop get the loop count in B : Note: we take
6582 only the lower order byte since shifting
6583 more that 32 bits make no sense anyway, ( the
6584 largest size of an object can be only 32 bits ) */
6586 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6587 emitcode ("inc", "b");
6588 freeAsmop (right, NULL, ic, TRUE);
6589 aopOp (left, ic, FALSE);
6590 aopOp (result, ic, FALSE);
6592 /* now move the left to the result if they are not the
6594 if (!sameRegs (AOP (left), AOP (result)) &&
6595 AOP_SIZE (result) > 1)
6598 size = AOP_SIZE (result);
6602 l = aopGet (AOP (left), offset, FALSE, TRUE);
6603 if (*l == '@' && IS_AOP_PREG (result))
6606 emitcode ("mov", "a,%s", l);
6607 aopPut (AOP (result), "a", offset);
6610 aopPut (AOP (result), l, offset);
6615 /* mov the highest order bit to OVR */
6616 tlbl = newiTempLabel (NULL);
6617 tlbl1 = newiTempLabel (NULL);
6619 size = AOP_SIZE (result);
6621 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6622 emitcode ("rlc", "a");
6623 emitcode ("mov", "ov,c");
6624 /* if it is only one byte then */
6627 l = aopGet (AOP (left), 0, FALSE, FALSE);
6629 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6630 emitcode ("", "%05d$:", tlbl->key + 100);
6631 emitcode ("mov", "c,ov");
6632 emitcode ("rrc", "a");
6633 emitcode ("", "%05d$:", tlbl1->key + 100);
6634 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6635 aopPut (AOP (result), "a", 0);
6639 reAdjustPreg (AOP (result));
6640 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6641 emitcode ("", "%05d$:", tlbl->key + 100);
6642 emitcode ("mov", "c,ov");
6645 l = aopGet (AOP (result), offset, FALSE, FALSE);
6647 emitcode ("rrc", "a");
6648 aopPut (AOP (result), "a", offset--);
6650 reAdjustPreg (AOP (result));
6651 emitcode ("", "%05d$:", tlbl1->key + 100);
6652 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6655 freeAsmop (left, NULL, ic, TRUE);
6656 freeAsmop (result, NULL, ic, TRUE);
6659 /*-----------------------------------------------------------------*/
6660 /* genRightShift - generate code for right shifting */
6661 /*-----------------------------------------------------------------*/
6663 genRightShift (iCode * ic)
6665 operand *right, *left, *result;
6669 symbol *tlbl, *tlbl1;
6671 /* if signed then we do it the hard way preserve the
6672 sign bit moving it inwards */
6673 retype = getSpec (operandType (IC_RESULT (ic)));
6675 if (!SPEC_USIGN (retype))
6677 genSignedRightShift (ic);
6681 /* signed & unsigned types are treated the same : i.e. the
6682 signed is NOT propagated inwards : quoting from the
6683 ANSI - standard : "for E1 >> E2, is equivalent to division
6684 by 2**E2 if unsigned or if it has a non-negative value,
6685 otherwise the result is implementation defined ", MY definition
6686 is that the sign does not get propagated */
6688 right = IC_RIGHT (ic);
6689 left = IC_LEFT (ic);
6690 result = IC_RESULT (ic);
6692 aopOp (right, ic, FALSE);
6694 /* if the shift count is known then do it
6695 as efficiently as possible */
6696 if (AOP_TYPE (right) == AOP_LIT)
6698 genRightShiftLiteral (left, right, result, ic, 0);
6702 /* shift count is unknown then we have to form
6703 a loop get the loop count in B : Note: we take
6704 only the lower order byte since shifting
6705 more that 32 bits make no sense anyway, ( the
6706 largest size of an object can be only 32 bits ) */
6708 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6709 emitcode ("inc", "b");
6710 freeAsmop (right, NULL, ic, TRUE);
6711 aopOp (left, ic, FALSE);
6712 aopOp (result, ic, FALSE);
6714 /* now move the left to the result if they are not the
6716 if (!sameRegs (AOP (left), AOP (result)) &&
6717 AOP_SIZE (result) > 1)
6720 size = AOP_SIZE (result);
6724 l = aopGet (AOP (left), offset, FALSE, TRUE);
6725 if (*l == '@' && IS_AOP_PREG (result))
6728 emitcode ("mov", "a,%s", l);
6729 aopPut (AOP (result), "a", offset);
6732 aopPut (AOP (result), l, offset);
6737 tlbl = newiTempLabel (NULL);
6738 tlbl1 = newiTempLabel (NULL);
6739 size = AOP_SIZE (result);
6742 /* if it is only one byte then */
6745 l = aopGet (AOP (left), 0, FALSE, FALSE);
6747 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6748 emitcode ("", "%05d$:", tlbl->key + 100);
6750 emitcode ("rrc", "a");
6751 emitcode ("", "%05d$:", tlbl1->key + 100);
6752 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6753 aopPut (AOP (result), "a", 0);
6757 reAdjustPreg (AOP (result));
6758 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6759 emitcode ("", "%05d$:", tlbl->key + 100);
6763 l = aopGet (AOP (result), offset, FALSE, FALSE);
6765 emitcode ("rrc", "a");
6766 aopPut (AOP (result), "a", offset--);
6768 reAdjustPreg (AOP (result));
6770 emitcode ("", "%05d$:", tlbl1->key + 100);
6771 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6774 freeAsmop (left, NULL, ic, TRUE);
6775 freeAsmop (result, NULL, ic, TRUE);
6778 /*-----------------------------------------------------------------*/
6779 /* genUnpackBits - generates code for unpacking bits */
6780 /*-----------------------------------------------------------------*/
6782 genUnpackBits (operand * result, char *rname, int ptype)
6790 etype = getSpec (operandType (result));
6791 rsize = getSize (operandType (result));
6792 /* read the first byte */
6798 emitcode ("mov", "a,@%s", rname);
6802 emitcode ("movx", "a,@%s", rname);
6806 emitcode ("movx", "a,@dptr");
6810 emitcode ("clr", "a");
6811 emitcode ("movc", "a,@a+dptr");
6815 emitcode ("lcall", "__gptrget");
6819 rlen = SPEC_BLEN (etype);
6821 /* if we have bitdisplacement then it fits */
6822 /* into this byte completely or if length is */
6823 /* less than a byte */
6824 if ((shCnt = SPEC_BSTR (etype)) ||
6825 (SPEC_BLEN (etype) <= 8))
6828 /* shift right acc */
6831 emitcode ("anl", "a,#0x%02x",
6832 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6833 aopPut (AOP (result), "a", offset++);
6837 /* bit field did not fit in a byte */
6838 aopPut (AOP (result), "a", offset++);
6847 emitcode ("inc", "%s", rname);
6848 emitcode ("mov", "a,@%s", rname);
6852 emitcode ("inc", "%s", rname);
6853 emitcode ("movx", "a,@%s", rname);
6857 emitcode ("inc", "dptr");
6858 emitcode ("movx", "a,@dptr");
6862 emitcode ("clr", "a");
6863 emitcode ("inc", "dptr");
6864 emitcode ("movc", "a,@a+dptr");
6868 emitcode ("inc", "dptr");
6869 emitcode ("lcall", "__gptrget");
6874 /* if we are done */
6878 aopPut (AOP (result), "a", offset++);
6884 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6886 aopPut (AOP (result), "a", offset++);
6894 aopPut (AOP (result), zero, offset++);
6900 /*-----------------------------------------------------------------*/
6901 /* genDataPointerGet - generates code when ptr offset is known */
6902 /*-----------------------------------------------------------------*/
6904 genDataPointerGet (operand * left,
6910 int size, offset = 0;
6911 aopOp (result, ic, TRUE);
6913 /* get the string representation of the name */
6914 l = aopGet (AOP (left), 0, FALSE, TRUE);
6915 size = AOP_SIZE (result);
6919 sprintf (buffer, "(%s + %d)", l + 1, offset);
6921 sprintf (buffer, "%s", l + 1);
6922 aopPut (AOP (result), buffer, offset++);
6925 freeAsmop (left, NULL, ic, TRUE);
6926 freeAsmop (result, NULL, ic, TRUE);
6929 /*-----------------------------------------------------------------*/
6930 /* genNearPointerGet - emitcode for near pointer fetch */
6931 /*-----------------------------------------------------------------*/
6933 genNearPointerGet (operand * left,
6941 sym_link *rtype, *retype;
6942 sym_link *ltype = operandType (left);
6945 rtype = operandType (result);
6946 retype = getSpec (rtype);
6948 aopOp (left, ic, FALSE);
6950 /* if left is rematerialisable and
6951 result is not bit variable type and
6952 the left is pointer to data space i.e
6953 lower 128 bytes of space */
6954 if (AOP_TYPE (left) == AOP_IMMD &&
6955 !IS_BITVAR (retype) &&
6956 DCL_TYPE (ltype) == POINTER)
6958 genDataPointerGet (left, result, ic);
6962 /* if the value is already in a pointer register
6963 then don't need anything more */
6964 if (!AOP_INPREG (AOP (left)))
6966 /* otherwise get a free pointer register */
6968 preg = getFreePtr (ic, &aop, FALSE);
6969 emitcode ("mov", "%s,%s",
6971 aopGet (AOP (left), 0, FALSE, TRUE));
6975 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6977 //aopOp (result, ic, FALSE);
6978 aopOp (result, ic, result?TRUE:FALSE);
6980 /* if bitfield then unpack the bits */
6981 if (IS_BITVAR (retype))
6982 genUnpackBits (result, rname, POINTER);
6985 /* we have can just get the values */
6986 int size = AOP_SIZE (result);
6991 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6994 emitcode ("mov", "a,@%s", rname);
6995 aopPut (AOP (result), "a", offset);
6999 sprintf (buffer, "@%s", rname);
7000 aopPut (AOP (result), buffer, offset);
7004 emitcode ("inc", "%s", rname);
7008 /* now some housekeeping stuff */
7009 if (aop) /* we had to allocate for this iCode */
7011 if (pi) { /* post increment present */
7012 aopPut(AOP ( left ),rname,0);
7014 freeAsmop (NULL, aop, ic, TRUE);
7018 /* we did not allocate which means left
7019 already in a pointer register, then
7020 if size > 0 && this could be used again
7021 we have to point it back to where it
7023 if ((AOP_SIZE (result) > 1 &&
7024 !OP_SYMBOL (left)->remat &&
7025 (OP_SYMBOL (left)->liveTo > ic->seq ||
7029 int size = AOP_SIZE (result) - 1;
7031 emitcode ("dec", "%s", rname);
7036 freeAsmop (left, NULL, ic, TRUE);
7037 freeAsmop (result, NULL, ic, TRUE);
7038 if (pi) pi->generated = 1;
7041 /*-----------------------------------------------------------------*/
7042 /* genPagedPointerGet - emitcode for paged pointer fetch */
7043 /*-----------------------------------------------------------------*/
7045 genPagedPointerGet (operand * left,
7053 sym_link *rtype, *retype;
7055 rtype = operandType (result);
7056 retype = getSpec (rtype);
7058 aopOp (left, ic, FALSE);
7060 /* if the value is already in a pointer register
7061 then don't need anything more */
7062 if (!AOP_INPREG (AOP (left)))
7064 /* otherwise get a free pointer register */
7066 preg = getFreePtr (ic, &aop, FALSE);
7067 emitcode ("mov", "%s,%s",
7069 aopGet (AOP (left), 0, FALSE, TRUE));
7073 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7075 aopOp (result, ic, FALSE);
7077 /* if bitfield then unpack the bits */
7078 if (IS_BITVAR (retype))
7079 genUnpackBits (result, rname, PPOINTER);
7082 /* we have can just get the values */
7083 int size = AOP_SIZE (result);
7089 emitcode ("movx", "a,@%s", rname);
7090 aopPut (AOP (result), "a", offset);
7095 emitcode ("inc", "%s", rname);
7099 /* now some housekeeping stuff */
7100 if (aop) /* we had to allocate for this iCode */
7102 if (pi) aopPut ( AOP (left), rname, 0);
7103 freeAsmop (NULL, aop, ic, TRUE);
7107 /* we did not allocate which means left
7108 already in a pointer register, then
7109 if size > 0 && this could be used again
7110 we have to point it back to where it
7112 if ((AOP_SIZE (result) > 1 &&
7113 !OP_SYMBOL (left)->remat &&
7114 (OP_SYMBOL (left)->liveTo > ic->seq ||
7118 int size = AOP_SIZE (result) - 1;
7120 emitcode ("dec", "%s", rname);
7125 freeAsmop (left, NULL, ic, TRUE);
7126 freeAsmop (result, NULL, ic, TRUE);
7127 if (pi) pi->generated = 1;
7131 /*-----------------------------------------------------------------*/
7132 /* genFarPointerGet - gget value from far space */
7133 /*-----------------------------------------------------------------*/
7135 genFarPointerGet (operand * left,
7136 operand * result, iCode * ic, iCode * pi)
7139 sym_link *retype = getSpec (operandType (result));
7141 aopOp (left, ic, FALSE);
7143 /* if the operand is already in dptr
7144 then we do nothing else we move the value to dptr */
7145 if (AOP_TYPE (left) != AOP_STR)
7147 /* if this is remateriazable */
7148 if (AOP_TYPE (left) == AOP_IMMD)
7149 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7151 { /* we need to get it byte by byte */
7152 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7153 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7156 /* so dptr know contains the address */
7157 aopOp (result, ic, FALSE);
7159 /* if bit then unpack */
7160 if (IS_BITVAR (retype))
7161 genUnpackBits (result, "dptr", FPOINTER);
7164 size = AOP_SIZE (result);
7169 emitcode ("movx", "a,@dptr");
7170 aopPut (AOP (result), "a", offset++);
7172 emitcode ("inc", "dptr");
7176 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7177 aopPut ( AOP (left), "dpl", 0);
7178 aopPut ( AOP (left), "dph", 1);
7181 freeAsmop (left, NULL, ic, TRUE);
7182 freeAsmop (result, NULL, ic, TRUE);
7185 /*-----------------------------------------------------------------*/
7186 /* genCodePointerGet - gget value from code space */
7187 /*-----------------------------------------------------------------*/
7189 genCodePointerGet (operand * left,
7190 operand * result, iCode * ic, iCode *pi)
7193 sym_link *retype = getSpec (operandType (result));
7195 aopOp (left, ic, FALSE);
7197 /* if the operand is already in dptr
7198 then we do nothing else we move the value to dptr */
7199 if (AOP_TYPE (left) != AOP_STR)
7201 /* if this is remateriazable */
7202 if (AOP_TYPE (left) == AOP_IMMD)
7203 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7205 { /* we need to get it byte by byte */
7206 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7207 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7210 /* so dptr know contains the address */
7211 aopOp (result, ic, FALSE);
7213 /* if bit then unpack */
7214 if (IS_BITVAR (retype))
7215 genUnpackBits (result, "dptr", CPOINTER);
7218 size = AOP_SIZE (result);
7223 emitcode ("clr", "a");
7224 emitcode ("movc", "a,@a+dptr");
7225 aopPut (AOP (result), "a", offset++);
7227 emitcode ("inc", "dptr");
7231 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7232 aopPut ( AOP (left), "dpl", 0);
7233 aopPut ( AOP (left), "dph", 1);
7236 freeAsmop (left, NULL, ic, TRUE);
7237 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* genGenPointerGet - gget value from generic pointer space */
7242 /*-----------------------------------------------------------------*/
7244 genGenPointerGet (operand * left,
7245 operand * result, iCode * ic, iCode *pi)
7248 sym_link *retype = getSpec (operandType (result));
7250 aopOp (left, ic, FALSE);
7252 /* if the operand is already in dptr
7253 then we do nothing else we move the value to dptr */
7254 if (AOP_TYPE (left) != AOP_STR)
7256 /* if this is remateriazable */
7257 if (AOP_TYPE (left) == AOP_IMMD)
7259 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7260 emitcode ("mov", "b,#%d", pointerCode (retype));
7263 { /* we need to get it byte by byte */
7264 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7265 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7266 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7269 /* so dptr know contains the address */
7270 aopOp (result, ic, FALSE);
7272 /* if bit then unpack */
7273 if (IS_BITVAR (retype))
7274 genUnpackBits (result, "dptr", GPOINTER);
7277 size = AOP_SIZE (result);
7282 emitcode ("lcall", "__gptrget");
7283 aopPut (AOP (result), "a", offset++);
7285 emitcode ("inc", "dptr");
7289 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7290 aopPut ( AOP (left), "dpl", 0);
7291 aopPut ( AOP (left), "dph", 1);
7294 freeAsmop (left, NULL, ic, TRUE);
7295 freeAsmop (result, NULL, ic, TRUE);
7298 /*-----------------------------------------------------------------*/
7299 /* genPointerGet - generate code for pointer get */
7300 /*-----------------------------------------------------------------*/
7302 genPointerGet (iCode * ic, iCode *pi)
7304 operand *left, *result;
7305 sym_link *type, *etype;
7308 left = IC_LEFT (ic);
7309 result = IC_RESULT (ic);
7311 /* depending on the type of pointer we need to
7312 move it to the correct pointer register */
7313 type = operandType (left);
7314 etype = getSpec (type);
7315 /* if left is of type of pointer then it is simple */
7316 if (IS_PTR (type) && !IS_FUNC (type->next))
7317 p_type = DCL_TYPE (type);
7320 /* we have to go by the storage class */
7321 p_type = PTR_TYPE (SPEC_OCLS (etype));
7324 /* now that we have the pointer type we assign
7325 the pointer values */
7331 genNearPointerGet (left, result, ic, pi);
7335 genPagedPointerGet (left, result, ic, pi);
7339 genFarPointerGet (left, result, ic, pi);
7343 genCodePointerGet (left, result, ic, pi);
7347 genGenPointerGet (left, result, ic, pi);
7353 /*-----------------------------------------------------------------*/
7354 /* genPackBits - generates code for packed bit storage */
7355 /*-----------------------------------------------------------------*/
7357 genPackBits (sym_link * etype,
7359 char *rname, int p_type)
7367 blen = SPEC_BLEN (etype);
7368 bstr = SPEC_BSTR (etype);
7370 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7373 /* if the bit lenth is less than or */
7374 /* it exactly fits a byte then */
7375 if (SPEC_BLEN (etype) <= 8)
7377 shCount = SPEC_BSTR (etype);
7379 /* shift left acc */
7382 if (SPEC_BLEN (etype) < 8)
7383 { /* if smaller than a byte */
7389 emitcode ("mov", "b,a");
7390 emitcode ("mov", "a,@%s", rname);
7394 emitcode ("mov", "b,a");
7395 emitcode ("movx", "a,@dptr");
7399 emitcode ("push", "b");
7400 emitcode ("push", "acc");
7401 emitcode ("lcall", "__gptrget");
7402 emitcode ("pop", "b");
7406 emitcode ("anl", "a,#0x%02x", (unsigned char)
7407 ((unsigned char) (0xFF << (blen + bstr)) |
7408 (unsigned char) (0xFF >> (8 - bstr))));
7409 emitcode ("orl", "a,b");
7410 if (p_type == GPOINTER)
7411 emitcode ("pop", "b");
7418 emitcode ("mov", "@%s,a", rname);
7422 emitcode ("movx", "@dptr,a");
7426 emitcode ("lcall", "__gptrput");
7431 if (SPEC_BLEN (etype) <= 8)
7434 emitcode ("inc", "%s", rname);
7435 rLen = SPEC_BLEN (etype);
7437 /* now generate for lengths greater than one byte */
7441 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7453 emitcode ("mov", "@%s,a", rname);
7456 emitcode ("mov", "@%s,%s", rname, l);
7461 emitcode ("movx", "@dptr,a");
7466 emitcode ("lcall", "__gptrput");
7469 emitcode ("inc", "%s", rname);
7474 /* last last was not complete */
7477 /* save the byte & read byte */
7481 emitcode ("mov", "b,a");
7482 emitcode ("mov", "a,@%s", rname);
7486 emitcode ("mov", "b,a");
7487 emitcode ("movx", "a,@dptr");
7491 emitcode ("push", "b");
7492 emitcode ("push", "acc");
7493 emitcode ("lcall", "__gptrget");
7494 emitcode ("pop", "b");
7498 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7499 emitcode ("orl", "a,b");
7502 if (p_type == GPOINTER)
7503 emitcode ("pop", "b");
7509 emitcode ("mov", "@%s,a", rname);
7513 emitcode ("movx", "@dptr,a");
7517 emitcode ("lcall", "__gptrput");
7521 /*-----------------------------------------------------------------*/
7522 /* genDataPointerSet - remat pointer to data space */
7523 /*-----------------------------------------------------------------*/
7525 genDataPointerSet (operand * right,
7529 int size, offset = 0;
7530 char *l, buffer[256];
7532 aopOp (right, ic, FALSE);
7534 l = aopGet (AOP (result), 0, FALSE, TRUE);
7535 size = AOP_SIZE (right);
7539 sprintf (buffer, "(%s + %d)", l + 1, offset);
7541 sprintf (buffer, "%s", l + 1);
7542 emitcode ("mov", "%s,%s", buffer,
7543 aopGet (AOP (right), offset++, FALSE, FALSE));
7546 freeAsmop (right, NULL, ic, TRUE);
7547 freeAsmop (result, NULL, ic, TRUE);
7550 /*-----------------------------------------------------------------*/
7551 /* genNearPointerSet - emitcode for near pointer put */
7552 /*-----------------------------------------------------------------*/
7554 genNearPointerSet (operand * right,
7562 sym_link *retype, *letype;
7563 sym_link *ptype = operandType (result);
7565 retype = getSpec (operandType (right));
7566 letype = getSpec (ptype);
7567 aopOp (result, ic, FALSE);
7569 /* if the result is rematerializable &
7570 in data space & not a bit variable */
7571 if (AOP_TYPE (result) == AOP_IMMD &&
7572 DCL_TYPE (ptype) == POINTER &&
7573 !IS_BITVAR (retype) &&
7574 !IS_BITVAR (letype))
7576 genDataPointerSet (right, result, ic);
7580 /* if the value is already in a pointer register
7581 then don't need anything more */
7582 if (!AOP_INPREG (AOP (result)))
7584 /* otherwise get a free pointer register */
7586 preg = getFreePtr (ic, &aop, FALSE);
7587 emitcode ("mov", "%s,%s",
7589 aopGet (AOP (result), 0, FALSE, TRUE));
7593 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7595 aopOp (right, ic, FALSE);
7597 /* if bitfield then unpack the bits */
7598 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7599 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7602 /* we have can just get the values */
7603 int size = AOP_SIZE (right);
7608 l = aopGet (AOP (right), offset, FALSE, TRUE);
7612 emitcode ("mov", "@%s,a", rname);
7615 emitcode ("mov", "@%s,%s", rname, l);
7617 emitcode ("inc", "%s", rname);
7622 /* now some housekeeping stuff */
7623 if (aop) /* we had to allocate for this iCode */
7625 if (pi) aopPut (AOP (result),rname,0);
7626 freeAsmop (NULL, aop, ic, TRUE);
7630 /* we did not allocate which means left
7631 already in a pointer register, then
7632 if size > 0 && this could be used again
7633 we have to point it back to where it
7635 if ((AOP_SIZE (right) > 1 &&
7636 !OP_SYMBOL (result)->remat &&
7637 (OP_SYMBOL (result)->liveTo > ic->seq ||
7641 int size = AOP_SIZE (right) - 1;
7643 emitcode ("dec", "%s", rname);
7648 if (pi) pi->generated = 1;
7649 freeAsmop (result, NULL, ic, TRUE);
7650 freeAsmop (right, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genPagedPointerSet - emitcode for Paged pointer put */
7655 /*-----------------------------------------------------------------*/
7657 genPagedPointerSet (operand * right,
7665 sym_link *retype, *letype;
7667 retype = getSpec (operandType (right));
7668 letype = getSpec (operandType (result));
7670 aopOp (result, ic, FALSE);
7672 /* if the value is already in a pointer register
7673 then don't need anything more */
7674 if (!AOP_INPREG (AOP (result)))
7676 /* otherwise get a free pointer register */
7678 preg = getFreePtr (ic, &aop, FALSE);
7679 emitcode ("mov", "%s,%s",
7681 aopGet (AOP (result), 0, FALSE, TRUE));
7685 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7687 aopOp (right, ic, FALSE);
7689 /* if bitfield then unpack the bits */
7690 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7691 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7694 /* we have can just get the values */
7695 int size = AOP_SIZE (right);
7700 l = aopGet (AOP (right), offset, FALSE, TRUE);
7703 emitcode ("movx", "@%s,a", rname);
7706 emitcode ("inc", "%s", rname);
7712 /* now some housekeeping stuff */
7713 if (aop) /* we had to allocate for this iCode */
7715 if (pi) aopPut (AOP (result),rname,0);
7716 freeAsmop (NULL, aop, ic, TRUE);
7720 /* we did not allocate which means left
7721 already in a pointer register, then
7722 if size > 0 && this could be used again
7723 we have to point it back to where it
7725 if (AOP_SIZE (right) > 1 &&
7726 !OP_SYMBOL (result)->remat &&
7727 (OP_SYMBOL (result)->liveTo > ic->seq ||
7730 int size = AOP_SIZE (right) - 1;
7732 emitcode ("dec", "%s", rname);
7737 if (pi) pi->generated = 1;
7738 freeAsmop (result, NULL, ic, TRUE);
7739 freeAsmop (right, NULL, ic, TRUE);
7744 /*-----------------------------------------------------------------*/
7745 /* genFarPointerSet - set value from far space */
7746 /*-----------------------------------------------------------------*/
7748 genFarPointerSet (operand * right,
7749 operand * result, iCode * ic, iCode * pi)
7752 sym_link *retype = getSpec (operandType (right));
7753 sym_link *letype = getSpec (operandType (result));
7754 aopOp (result, ic, FALSE);
7756 /* if the operand is already in dptr
7757 then we do nothing else we move the value to dptr */
7758 if (AOP_TYPE (result) != AOP_STR)
7760 /* if this is remateriazable */
7761 if (AOP_TYPE (result) == AOP_IMMD)
7762 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7764 { /* we need to get it byte by byte */
7765 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7766 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7769 /* so dptr know contains the address */
7770 aopOp (right, ic, FALSE);
7772 /* if bit then unpack */
7773 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7774 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7777 size = AOP_SIZE (right);
7782 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7784 emitcode ("movx", "@dptr,a");
7786 emitcode ("inc", "dptr");
7789 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7790 aopPut (AOP(result),"dpl",0);
7791 aopPut (AOP(result),"dph",1);
7794 freeAsmop (result, NULL, ic, TRUE);
7795 freeAsmop (right, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genGenPointerSet - set value from generic pointer space */
7800 /*-----------------------------------------------------------------*/
7802 genGenPointerSet (operand * right,
7803 operand * result, iCode * ic, iCode * pi)
7806 sym_link *retype = getSpec (operandType (right));
7807 sym_link *letype = getSpec (operandType (result));
7809 aopOp (result, ic, FALSE);
7811 /* if the operand is already in dptr
7812 then we do nothing else we move the value to dptr */
7813 if (AOP_TYPE (result) != AOP_STR)
7815 /* if this is remateriazable */
7816 if (AOP_TYPE (result) == AOP_IMMD)
7818 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7819 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7822 { /* we need to get it byte by byte */
7823 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7824 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7825 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7828 /* so dptr know contains the address */
7829 aopOp (right, ic, FALSE);
7831 /* if bit then unpack */
7832 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7833 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7836 size = AOP_SIZE (right);
7841 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7843 emitcode ("lcall", "__gptrput");
7845 emitcode ("inc", "dptr");
7849 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7850 aopPut (AOP(result),"dpl",0);
7851 aopPut (AOP(result),"dph",1);
7854 freeAsmop (result, NULL, ic, TRUE);
7855 freeAsmop (right, NULL, ic, TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genPointerSet - stores the value into a pointer location */
7860 /*-----------------------------------------------------------------*/
7862 genPointerSet (iCode * ic, iCode *pi)
7864 operand *right, *result;
7865 sym_link *type, *etype;
7868 right = IC_RIGHT (ic);
7869 result = IC_RESULT (ic);
7871 /* depending on the type of pointer we need to
7872 move it to the correct pointer register */
7873 type = operandType (result);
7874 etype = getSpec (type);
7875 /* if left is of type of pointer then it is simple */
7876 if (IS_PTR (type) && !IS_FUNC (type->next))
7878 p_type = DCL_TYPE (type);
7882 /* we have to go by the storage class */
7883 p_type = PTR_TYPE (SPEC_OCLS (etype));
7886 /* now that we have the pointer type we assign
7887 the pointer values */
7893 genNearPointerSet (right, result, ic, pi);
7897 genPagedPointerSet (right, result, ic, pi);
7901 genFarPointerSet (right, result, ic, pi);
7905 genGenPointerSet (right, result, ic, pi);
7911 /*-----------------------------------------------------------------*/
7912 /* genIfx - generate code for Ifx statement */
7913 /*-----------------------------------------------------------------*/
7915 genIfx (iCode * ic, iCode * popIc)
7917 operand *cond = IC_COND (ic);
7920 aopOp (cond, ic, FALSE);
7922 /* get the value into acc */
7923 if (AOP_TYPE (cond) != AOP_CRY)
7927 /* the result is now in the accumulator */
7928 freeAsmop (cond, NULL, ic, TRUE);
7930 /* if there was something to be popped then do it */
7934 /* if the condition is a bit variable */
7935 if (isbit && IS_ITEMP (cond) &&
7937 genIfxJump (ic, SPIL_LOC (cond)->rname);
7938 else if (isbit && !IS_ITEMP (cond))
7939 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7941 genIfxJump (ic, "a");
7946 /*-----------------------------------------------------------------*/
7947 /* genAddrOf - generates code for address of */
7948 /*-----------------------------------------------------------------*/
7950 genAddrOf (iCode * ic)
7952 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7955 aopOp (IC_RESULT (ic), ic, FALSE);
7957 /* if the operand is on the stack then we
7958 need to get the stack offset of this
7962 /* if it has an offset then we need to compute
7966 emitcode ("mov", "a,_bp");
7967 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7968 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7972 /* we can just move _bp */
7973 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7975 /* fill the result with zero */
7976 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7981 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7987 /* object not on stack then we need the name */
7988 size = AOP_SIZE (IC_RESULT (ic));
7993 char s[SDCC_NAME_MAX];
7995 sprintf (s, "#(%s >> %d)",
7999 sprintf (s, "#%s", sym->rname);
8000 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8008 /*-----------------------------------------------------------------*/
8009 /* genFarFarAssign - assignment when both are in far space */
8010 /*-----------------------------------------------------------------*/
8012 genFarFarAssign (operand * result, operand * right, iCode * ic)
8014 int size = AOP_SIZE (right);
8017 /* first push the right side on to the stack */
8020 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8022 emitcode ("push", "acc");
8025 freeAsmop (right, NULL, ic, FALSE);
8026 /* now assign DPTR to result */
8027 aopOp (result, ic, FALSE);
8028 size = AOP_SIZE (result);
8031 emitcode ("pop", "acc");
8032 aopPut (AOP (result), "a", --offset);
8034 freeAsmop (result, NULL, ic, FALSE);
8038 /*-----------------------------------------------------------------*/
8039 /* genAssign - generate code for assignment */
8040 /*-----------------------------------------------------------------*/
8042 genAssign (iCode * ic)
8044 operand *result, *right;
8046 unsigned long lit = 0L;
8048 D(emitcode(";","genAssign"));
8050 result = IC_RESULT (ic);
8051 right = IC_RIGHT (ic);
8053 /* if they are the same */
8054 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8057 aopOp (right, ic, FALSE);
8059 /* special case both in far space */
8060 if (AOP_TYPE (right) == AOP_DPTR &&
8061 IS_TRUE_SYMOP (result) &&
8062 isOperandInFarSpace (result))
8065 genFarFarAssign (result, right, ic);
8069 aopOp (result, ic, TRUE);
8071 /* if they are the same registers */
8072 if (sameRegs (AOP (right), AOP (result)))
8075 /* if the result is a bit */
8076 if (AOP_TYPE (result) == AOP_CRY)
8079 /* if the right size is a literal then
8080 we know what the value is */
8081 if (AOP_TYPE (right) == AOP_LIT)
8083 if (((int) operandLitValue (right)))
8084 aopPut (AOP (result), one, 0);
8086 aopPut (AOP (result), zero, 0);
8090 /* the right is also a bit variable */
8091 if (AOP_TYPE (right) == AOP_CRY)
8093 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8094 aopPut (AOP (result), "c", 0);
8100 aopPut (AOP (result), "a", 0);
8104 /* bit variables done */
8106 size = AOP_SIZE (result);
8108 if (AOP_TYPE (right) == AOP_LIT)
8109 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8111 (AOP_TYPE (result) != AOP_REG) &&
8112 (AOP_TYPE (right) == AOP_LIT) &&
8113 !IS_FLOAT (operandType (right)) &&
8116 emitcode ("clr", "a");
8119 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8120 aopPut (AOP (result), "a", size);
8122 aopPut (AOP (result),
8123 aopGet (AOP (right), size, FALSE, FALSE),
8131 aopPut (AOP (result),
8132 aopGet (AOP (right), offset, FALSE, FALSE),
8139 freeAsmop (right, NULL, ic, TRUE);
8140 freeAsmop (result, NULL, ic, TRUE);
8143 /*-----------------------------------------------------------------*/
8144 /* genJumpTab - genrates code for jump table */
8145 /*-----------------------------------------------------------------*/
8147 genJumpTab (iCode * ic)
8152 aopOp (IC_JTCOND (ic), ic, FALSE);
8153 /* get the condition into accumulator */
8154 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8156 /* multiply by three */
8157 emitcode ("add", "a,acc");
8158 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8159 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8161 jtab = newiTempLabel (NULL);
8162 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8163 emitcode ("jmp", "@a+dptr");
8164 emitcode ("", "%05d$:", jtab->key + 100);
8165 /* now generate the jump labels */
8166 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8167 jtab = setNextItem (IC_JTLABELS (ic)))
8168 emitcode ("ljmp", "%05d$", jtab->key + 100);
8172 /*-----------------------------------------------------------------*/
8173 /* genCast - gen code for casting */
8174 /*-----------------------------------------------------------------*/
8176 genCast (iCode * ic)
8178 operand *result = IC_RESULT (ic);
8179 sym_link *ctype = operandType (IC_LEFT (ic));
8180 sym_link *rtype = operandType (IC_RIGHT (ic));
8181 operand *right = IC_RIGHT (ic);
8184 D(emitcode(";", "genCast"));
8186 /* if they are equivalent then do nothing */
8187 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8190 aopOp (right, ic, FALSE);
8191 aopOp (result, ic, FALSE);
8193 /* if the result is a bit */
8194 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8195 if (IS_BITVAR(OP_SYMBOL(result)->type))
8197 /* if the right size is a literal then
8198 we know what the value is */
8199 if (AOP_TYPE (right) == AOP_LIT)
8201 if (((int) operandLitValue (right)))
8202 aopPut (AOP (result), one, 0);
8204 aopPut (AOP (result), zero, 0);
8209 /* the right is also a bit variable */
8210 if (AOP_TYPE (right) == AOP_CRY)
8212 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8213 aopPut (AOP (result), "c", 0);
8219 aopPut (AOP (result), "a", 0);
8223 /* if they are the same size : or less */
8224 if (AOP_SIZE (result) <= AOP_SIZE (right))
8227 /* if they are in the same place */
8228 if (sameRegs (AOP (right), AOP (result)))
8231 /* if they in different places then copy */
8232 size = AOP_SIZE (result);
8236 aopPut (AOP (result),
8237 aopGet (AOP (right), offset, FALSE, FALSE),
8245 /* if the result is of type pointer */
8250 sym_link *type = operandType (right);
8251 sym_link *etype = getSpec (type);
8253 /* pointer to generic pointer */
8254 if (IS_GENPTR (ctype))
8259 p_type = DCL_TYPE (type);
8262 if (SPEC_SCLS(etype)==S_REGISTER) {
8263 // let's assume it is a generic pointer
8266 /* we have to go by the storage class */
8267 p_type = PTR_TYPE (SPEC_OCLS (etype));
8271 /* the first two bytes are known */
8272 size = GPTRSIZE - 1;
8276 aopPut (AOP (result),
8277 aopGet (AOP (right), offset, FALSE, FALSE),
8281 /* the last byte depending on type */
8297 case PPOINTER: // what the fck is this?
8302 /* this should never happen */
8303 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8304 "got unknown pointer type");
8307 aopPut (AOP (result), l, GPTRSIZE - 1);
8311 /* just copy the pointers */
8312 size = AOP_SIZE (result);
8316 aopPut (AOP (result),
8317 aopGet (AOP (right), offset, FALSE, FALSE),
8324 /* so we now know that the size of destination is greater
8325 than the size of the source */
8326 /* we move to result for the size of source */
8327 size = AOP_SIZE (right);
8331 aopPut (AOP (result),
8332 aopGet (AOP (right), offset, FALSE, FALSE),
8337 /* now depending on the sign of the source && destination */
8338 size = AOP_SIZE (result) - AOP_SIZE (right);
8339 /* if unsigned or not an integral type */
8340 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8343 aopPut (AOP (result), zero, offset++);
8347 /* we need to extend the sign :{ */
8348 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8351 emitcode ("rlc", "a");
8352 emitcode ("subb", "a,acc");
8354 aopPut (AOP (result), "a", offset++);
8357 /* we are done hurray !!!! */
8360 freeAsmop (right, NULL, ic, TRUE);
8361 freeAsmop (result, NULL, ic, TRUE);
8365 /*-----------------------------------------------------------------*/
8366 /* genDjnz - generate decrement & jump if not zero instrucion */
8367 /*-----------------------------------------------------------------*/
8369 genDjnz (iCode * ic, iCode * ifx)
8375 /* if the if condition has a false label
8376 then we cannot save */
8380 /* if the minus is not of the form
8382 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8383 !IS_OP_LITERAL (IC_RIGHT (ic)))
8386 if (operandLitValue (IC_RIGHT (ic)) != 1)
8389 /* if the size of this greater than one then no
8391 if (getSize (operandType (IC_RESULT (ic))) > 1)
8394 /* otherwise we can save BIG */
8395 lbl = newiTempLabel (NULL);
8396 lbl1 = newiTempLabel (NULL);
8398 aopOp (IC_RESULT (ic), ic, FALSE);
8400 if (AOP_NEEDSACC(IC_RESULT(ic)))
8402 /* If the result is accessed indirectly via
8403 * the accumulator, we must explicitly write
8404 * it back after the decrement.
8406 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8408 if (strcmp(rByte, "a"))
8410 /* Something is hopelessly wrong */
8411 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8412 __FILE__, __LINE__);
8413 /* We can just give up; the generated code will be inefficient,
8416 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8419 emitcode ("dec", "%s", rByte);
8420 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8421 emitcode ("jnz", "%05d$", lbl->key + 100);
8423 else if (IS_AOP_PREG (IC_RESULT (ic)))
8425 emitcode ("dec", "%s",
8426 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8427 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8428 emitcode ("jnz", "%05d$", lbl->key + 100);
8432 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8435 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8436 emitcode ("", "%05d$:", lbl->key + 100);
8437 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8438 emitcode ("", "%05d$:", lbl1->key + 100);
8440 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8445 /*-----------------------------------------------------------------*/
8446 /* genReceive - generate code for a receive iCode */
8447 /*-----------------------------------------------------------------*/
8449 genReceive (iCode * ic)
8451 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8452 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8453 IS_TRUE_SYMOP (IC_RESULT (ic))))
8456 int size = getSize (operandType (IC_RESULT (ic)));
8457 int offset = fReturnSizeMCS51 - size;
8460 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8461 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8464 aopOp (IC_RESULT (ic), ic, FALSE);
8465 size = AOP_SIZE (IC_RESULT (ic));
8469 emitcode ("pop", "acc");
8470 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8477 aopOp (IC_RESULT (ic), ic, FALSE);
8479 assignResultValue (IC_RESULT (ic));
8482 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* gen51AggregateAssign - copy complete array's or structures */
8487 /*-----------------------------------------------------------------*/
8488 void gen51AggregateAssign(iCode *ic) {
8489 operand *left=IC_LEFT(ic);
8490 operand *right=IC_RIGHT(ic);
8491 char *fromName=OP_SYMBOL(right)->rname;
8492 char *toName=OP_SYMBOL(left)->rname;
8493 int fromSize=getSize(OP_SYMBOL(right)->type);
8494 int toSize=getSize(OP_SYMBOL(left)->type);
8497 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8498 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8499 // well, this code isn't used yet from anywhere else as for initialising
8500 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8504 if (fromSize!=toSize) {
8505 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8506 ic->filename, ic->lineno);
8511 // use the generic memcpy() for now
8512 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8513 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8514 emitcode ("mov", "a,#%s", fromName);
8515 emitcode ("movx", "@dptr,a");
8516 emitcode ("inc", "dptr");
8517 emitcode ("mov", "a,#(%s>>8)", fromName);
8518 emitcode ("movx", "@dptr,a");
8519 emitcode ("inc", "dptr");
8520 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8521 emitcode ("movx", "@dptr,a");
8522 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8523 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8524 emitcode ("movx", "@dptr,a");
8525 emitcode ("inc", "dptr");
8526 emitcode ("mov", "a,#(%d>>8)", count);
8527 emitcode ("movx", "@dptr,a");
8528 emitcode ("mov", "dptr,#%s", toName);
8529 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8530 emitcode ("lcall", "_memcpy");
8532 // more efficient, but will require the native_memcpy_cs2xs
8533 emitcode ("mov", "r0,#%s", fromName);
8534 emitcode ("mov", "r1,#(%s>>8)", fromName);
8535 emitcode ("mov", "r2,#%s", toName);
8536 emitcode ("mov", "r3,#(%s>>8)", toName);
8537 emitcode ("mov", "r4,#%d", count);
8538 emitcode ("mov", "r5,#(%d>>8)", count);
8539 emitcode ("lcall", "_native_memcpy_cs2xs");
8543 /*-----------------------------------------------------------------*/
8544 /* gen51Code - generate code for 8051 based controllers */
8545 /*-----------------------------------------------------------------*/
8547 gen51Code (iCode * lic)
8552 lineHead = lineCurr = NULL;
8554 /* print the allocation information */
8556 printAllocInfo (currFunc, codeOutFile);
8557 /* if debug information required */
8558 /* if (options.debug && currFunc) { */
8559 if (options.debug && currFunc)
8561 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8563 if (IS_STATIC (currFunc->etype))
8564 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8566 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8569 /* stack pointer name */
8570 if (options.useXstack)
8576 for (ic = lic; ic; ic = ic->next)
8579 if (cln != ic->lineno)
8584 emitcode ("", "C$%s$%d$%d$%d ==.",
8585 FileBaseName (ic->filename), ic->lineno,
8586 ic->level, ic->block);
8589 emitcode (";", "%s %d", ic->filename, ic->lineno);
8592 /* if the result is marked as
8593 spilt and rematerializable or code for
8594 this has already been generated then
8596 if (resultRemat (ic) || ic->generated)
8599 /* depending on the operation */
8619 /* IPOP happens only when trying to restore a
8620 spilt live range, if there is an ifx statement
8621 following this pop then the if statement might
8622 be using some of the registers being popped which
8623 would destory the contents of the register so
8624 we need to check for this condition and handle it */
8626 ic->next->op == IFX &&
8627 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8628 genIfx (ic->next, ic);
8646 genEndFunction (ic);
8666 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8683 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8687 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8694 /* note these two are xlated by algebraic equivalence
8695 during parsing SDCC.y */
8696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8697 "got '>=' or '<=' shouldn't have come here");
8701 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8713 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8717 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8721 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8748 case GET_VALUE_AT_ADDRESS:
8749 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8753 if (POINTER_SET (ic))
8754 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8780 addSet (&_G.sendSet, ic);
8784 gen51AggregateAssign(ic);
8793 /* now we are ready to call the
8794 peep hole optimizer */
8795 if (!options.nopeep)
8796 peepHole (&lineHead);
8798 /* now do the actual printing */
8799 printLine (lineHead, codeOutFile);