1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
385 val += (int) operandLitValue (IC_RIGHT (ic));
386 else if (ic->op == '-')
387 val -= (int) operandLitValue (IC_RIGHT (ic));
391 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
395 sprintf (buffer, "(%s %c 0x%04x)",
396 OP_SYMBOL (IC_LEFT (ic))->rname,
397 val >= 0 ? '+' : '-',
400 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
402 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
403 strcpy (aop->aopu.aop_immd, buffer);
407 /*-----------------------------------------------------------------*/
408 /* regsInCommon - two operands have some registers in common */
409 /*-----------------------------------------------------------------*/
411 regsInCommon (operand * op1, operand * op2)
416 /* if they have registers in common */
417 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
420 sym1 = OP_SYMBOL (op1);
421 sym2 = OP_SYMBOL (op2);
423 if (sym1->nRegs == 0 || sym2->nRegs == 0)
426 for (i = 0; i < sym1->nRegs; i++)
432 for (j = 0; j < sym2->nRegs; j++)
437 if (sym2->regs[j] == sym1->regs[i])
445 /*-----------------------------------------------------------------*/
446 /* operandsEqu - equivalent */
447 /*-----------------------------------------------------------------*/
449 operandsEqu (operand * op1, operand * op2)
453 /* if they not symbols */
454 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
457 sym1 = OP_SYMBOL (op1);
458 sym2 = OP_SYMBOL (op2);
460 /* if both are itemps & one is spilt
461 and the other is not then false */
462 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
463 sym1->isspilt != sym2->isspilt)
466 /* if they are the same */
470 if (strcmp (sym1->rname, sym2->rname) == 0)
474 /* if left is a tmp & right is not */
475 if (IS_ITEMP (op1) &&
478 (sym1->usl.spillLoc == sym2))
481 if (IS_ITEMP (op2) &&
485 (sym2->usl.spillLoc == sym1))
491 /*-----------------------------------------------------------------*/
492 /* sameRegs - two asmops have the same registers */
493 /*-----------------------------------------------------------------*/
495 sameRegs (asmop * aop1, asmop * aop2)
502 if (aop1->type != AOP_REG ||
503 aop2->type != AOP_REG)
506 if (aop1->size != aop2->size)
509 for (i = 0; i < aop1->size; i++)
510 if (aop1->aopu.aop_reg[i] !=
511 aop2->aopu.aop_reg[i])
517 /*-----------------------------------------------------------------*/
518 /* aopOp - allocates an asmop for an operand : */
519 /*-----------------------------------------------------------------*/
521 aopOp (operand * op, iCode * ic, bool result)
530 /* if this a literal */
531 if (IS_OP_LITERAL (op))
533 op->aop = aop = newAsmop (AOP_LIT);
534 aop->aopu.aop_lit = op->operand.valOperand;
535 aop->size = getSize (operandType (op));
539 /* if already has a asmop then continue */
543 /* if the underlying symbol has a aop */
544 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
546 op->aop = OP_SYMBOL (op)->aop;
550 /* if this is a true symbol */
551 if (IS_TRUE_SYMOP (op))
553 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
557 /* this is a temporary : this has
563 e) can be a return use only */
565 sym = OP_SYMBOL (op);
567 /* if the type is a conditional */
568 if (sym->regType == REG_CND)
570 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
575 /* if it is spilt then two situations
577 b) has a spill location */
578 if (sym->isspilt || sym->nRegs == 0)
581 /* rematerialize it NOW */
584 sym->aop = op->aop = aop =
586 aop->size = getSize (sym->type);
593 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
594 aop->size = getSize (sym->type);
595 for (i = 0; i < 2; i++)
596 aop->aopu.aop_str[i] = accUse[i];
604 aop = op->aop = sym->aop = newAsmop (AOP_STR);
605 aop->size = getSize (sym->type);
606 for (i = 0; i < fReturnSizeMCS51; i++)
607 aop->aopu.aop_str[i] = fReturn[i];
611 /* else spill location */
612 sym->aop = op->aop = aop =
613 aopForSym (ic, sym->usl.spillLoc, result);
614 aop->size = getSize (sym->type);
618 /* must be in a register */
619 sym->aop = op->aop = aop = newAsmop (AOP_REG);
620 aop->size = sym->nRegs;
621 for (i = 0; i < sym->nRegs; i++)
622 aop->aopu.aop_reg[i] = sym->regs[i];
625 /*-----------------------------------------------------------------*/
626 /* freeAsmop - free up the asmop given to an operand */
627 /*----------------------------------------------------------------*/
629 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
646 /* depending on the asmop type only three cases need work AOP_RO
647 , AOP_R1 && AOP_STK */
655 emitcode ("pop", "ar0");
659 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 emitcode ("pop", "ar1");
671 bitVectUnSetBit (ic->rUsed, R1_IDX);
677 int stk = aop->aopu.aop_stk + aop->size;
678 bitVectUnSetBit (ic->rUsed, R0_IDX);
679 bitVectUnSetBit (ic->rUsed, R1_IDX);
681 getFreePtr (ic, &aop, FALSE);
685 emitcode ("mov", "a,_bp");
686 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
687 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
691 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
696 emitcode ("pop", "acc");
697 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
700 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
703 freeAsmop (op, NULL, ic, TRUE);
706 emitcode ("pop", "ar0");
712 emitcode ("pop", "ar1");
719 /* all other cases just dealloc */
725 OP_SYMBOL (op)->aop = NULL;
726 /* if the symbol has a spill */
728 SPIL_LOC (op)->aop = NULL;
733 /*-----------------------------------------------------------------*/
734 /* aopGet - for fetching value of the aop */
735 /*-----------------------------------------------------------------*/
737 aopGet (asmop * aop, int offset, bool bit16, bool dname)
742 /* offset is greater than
744 if (offset > (aop->size - 1) &&
745 aop->type != AOP_LIT)
748 /* depending on type */
754 /* if we need to increment it */
755 while (offset > aop->coff)
757 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
761 while (offset < aop->coff)
763 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
770 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
771 return (dname ? "acc" : "a");
773 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
774 rs = Safe_calloc (1, strlen (s) + 1);
779 while (offset > aop->coff)
781 emitcode ("inc", "dptr");
785 while (offset < aop->coff)
787 emitcode ("lcall", "__decdptr");
794 emitcode ("clr", "a");
795 emitcode ("movc", "a,@a+dptr");
799 emitcode ("movx", "a,@dptr");
801 return (dname ? "acc" : "a");
806 sprintf (s, "#%s", aop->aopu.aop_immd);
808 sprintf (s, "#(%s >> %d)",
814 rs = Safe_calloc (1, strlen (s) + 1);
820 sprintf (s, "(%s + %d)",
824 sprintf (s, "%s", aop->aopu.aop_dir);
825 rs = Safe_calloc (1, strlen (s) + 1);
831 return aop->aopu.aop_reg[offset]->dname;
833 return aop->aopu.aop_reg[offset]->name;
836 emitcode ("clr", "a");
837 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
838 emitcode ("rlc", "a");
839 return (dname ? "acc" : "a");
842 if (!offset && dname)
844 return aop->aopu.aop_str[offset];
847 return aopLiteral (aop->aopu.aop_lit, offset);
851 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
855 return aop->aopu.aop_str[offset];
859 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
860 "aopget got unsupported aop->type");
863 /*-----------------------------------------------------------------*/
864 /* aopPut - puts a string for a aop */
865 /*-----------------------------------------------------------------*/
867 aopPut (asmop * aop, char *s, int offset)
871 if (aop->size && offset > (aop->size - 1))
873 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
874 "aopPut got offset > aop->size");
878 /* will assign value to value */
879 /* depending on where it is ofcourse */
884 sprintf (d, "(%s + %d)",
885 aop->aopu.aop_dir, offset);
887 sprintf (d, "%s", aop->aopu.aop_dir);
890 emitcode ("mov", "%s,%s", d, s);
895 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
896 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
899 strcmp (s, "r0") == 0 ||
900 strcmp (s, "r1") == 0 ||
901 strcmp (s, "r2") == 0 ||
902 strcmp (s, "r3") == 0 ||
903 strcmp (s, "r4") == 0 ||
904 strcmp (s, "r5") == 0 ||
905 strcmp (s, "r6") == 0 ||
906 strcmp (s, "r7") == 0)
907 emitcode ("mov", "%s,%s",
908 aop->aopu.aop_reg[offset]->dname, s);
910 emitcode ("mov", "%s,%s",
911 aop->aopu.aop_reg[offset]->name, s);
918 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
919 "aopPut writting to code space");
923 while (offset > aop->coff)
926 emitcode ("inc", "dptr");
929 while (offset < aop->coff)
932 emitcode ("lcall", "__decdptr");
937 /* if not in accumulater */
940 emitcode ("movx", "@dptr,a");
945 while (offset > aop->coff)
948 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
950 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
966 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
968 else if (strcmp (s, "r0") == 0 ||
969 strcmp (s, "r1") == 0 ||
970 strcmp (s, "r2") == 0 ||
971 strcmp (s, "r3") == 0 ||
972 strcmp (s, "r4") == 0 ||
973 strcmp (s, "r5") == 0 ||
974 strcmp (s, "r6") == 0 ||
975 strcmp (s, "r7") == 0)
978 sprintf (buffer, "a%s", s);
979 emitcode ("mov", "@%s,%s",
980 aop->aopu.aop_ptr->name, buffer);
983 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
988 if (strcmp (s, "a") == 0)
989 emitcode ("push", "acc");
991 emitcode ("push", "%s", s);
996 /* if bit variable */
997 if (!aop->aopu.aop_dir)
999 emitcode ("clr", "a");
1000 emitcode ("rlc", "a");
1005 emitcode ("clr", "%s", aop->aopu.aop_dir);
1007 emitcode ("setb", "%s", aop->aopu.aop_dir);
1008 else if (!strcmp (s, "c"))
1009 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1012 if (strcmp (s, "a"))
1017 symbol *lbl = newiTempLabel (NULL);
1018 emitcode ("clr", "c");
1019 emitcode ("jz", "%05d$", lbl->key + 100);
1020 emitcode ("cpl", "c");
1021 emitcode ("", "%05d$:", lbl->key + 100);
1022 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1030 if (strcmp (aop->aopu.aop_str[offset], s))
1031 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1036 if (!offset && (strcmp (s, "acc") == 0))
1039 if (strcmp (aop->aopu.aop_str[offset], s))
1040 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1044 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1045 "aopPut got unsupported aop->type");
1053 /*-----------------------------------------------------------------*/
1054 /* pointToEnd :- points to the last byte of the operand */
1055 /*-----------------------------------------------------------------*/
1057 pointToEnd (asmop * aop)
1063 aop->coff = count = (aop->size - 1);
1069 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1073 emitcode ("inc", "dptr");
1080 /*-----------------------------------------------------------------*/
1081 /* reAdjustPreg - points a register back to where it should */
1082 /*-----------------------------------------------------------------*/
1084 reAdjustPreg (asmop * aop)
1086 if ((aop->coff==0) || aop->size <= 1)
1094 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1099 emitcode ("lcall", "__decdptr");
1106 #define AOP(op) op->aop
1107 #define AOP_TYPE(op) AOP(op)->type
1108 #define AOP_SIZE(op) AOP(op)->size
1109 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1110 AOP_TYPE(x) == AOP_R0))
1112 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1113 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1115 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1116 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1117 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1119 /*-----------------------------------------------------------------*/
1120 /* genNotFloat - generates not for float operations */
1121 /*-----------------------------------------------------------------*/
1123 genNotFloat (operand * op, operand * res)
1129 /* we will put 127 in the first byte of
1131 aopPut (AOP (res), "#127", 0);
1132 size = AOP_SIZE (op) - 1;
1135 l = aopGet (op->aop, offset++, FALSE, FALSE);
1140 emitcode ("orl", "a,%s",
1142 offset++, FALSE, FALSE));
1145 tlbl = newiTempLabel (NULL);
1146 aopPut (res->aop, one, 1);
1147 emitcode ("jz", "%05d$", (tlbl->key + 100));
1148 aopPut (res->aop, zero, 1);
1149 emitcode ("", "%05d$:", (tlbl->key + 100));
1151 size = res->aop->size - 2;
1153 /* put zeros in the rest */
1155 aopPut (res->aop, zero, offset++);
1158 /*-----------------------------------------------------------------*/
1159 /* opIsGptr: returns non-zero if the passed operand is */
1160 /* a generic pointer type. */
1161 /*-----------------------------------------------------------------*/
1163 opIsGptr (operand * op)
1165 sym_link *type = operandType (op);
1167 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1174 /*-----------------------------------------------------------------*/
1175 /* getDataSize - get the operand data size */
1176 /*-----------------------------------------------------------------*/
1178 getDataSize (operand * op)
1181 size = AOP_SIZE (op);
1182 if (size == GPTRSIZE)
1184 sym_link *type = operandType (op);
1185 if (IS_GENPTR (type))
1187 /* generic pointer; arithmetic operations
1188 * should ignore the high byte (pointer type).
1196 /*-----------------------------------------------------------------*/
1197 /* outAcc - output Acc */
1198 /*-----------------------------------------------------------------*/
1200 outAcc (operand * result)
1203 size = getDataSize (result);
1206 aopPut (AOP (result), "a", 0);
1209 /* unsigned or positive */
1212 aopPut (AOP (result), zero, offset++);
1217 /*-----------------------------------------------------------------*/
1218 /* outBitC - output a bit C */
1219 /*-----------------------------------------------------------------*/
1221 outBitC (operand * result)
1223 /* if the result is bit */
1224 if (AOP_TYPE (result) == AOP_CRY)
1225 aopPut (AOP (result), "c", 0);
1228 emitcode ("clr", "a");
1229 emitcode ("rlc", "a");
1234 /*-----------------------------------------------------------------*/
1235 /* toBoolean - emit code for orl a,operator(sizeop) */
1236 /*-----------------------------------------------------------------*/
1238 toBoolean (operand * oper)
1240 int size = AOP_SIZE (oper) - 1;
1242 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1244 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1248 /*-----------------------------------------------------------------*/
1249 /* genNot - generate code for ! operation */
1250 /*-----------------------------------------------------------------*/
1255 sym_link *optype = operandType (IC_LEFT (ic));
1257 /* assign asmOps to operand & result */
1258 aopOp (IC_LEFT (ic), ic, FALSE);
1259 aopOp (IC_RESULT (ic), ic, TRUE);
1261 /* if in bit space then a special case */
1262 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1264 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1265 emitcode ("cpl", "c");
1266 outBitC (IC_RESULT (ic));
1270 /* if type float then do float */
1271 if (IS_FLOAT (optype))
1273 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1277 toBoolean (IC_LEFT (ic));
1279 tlbl = newiTempLabel (NULL);
1280 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1281 emitcode ("", "%05d$:", tlbl->key + 100);
1282 outBitC (IC_RESULT (ic));
1285 /* release the aops */
1286 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* genCpl - generate code for complement */
1293 /*-----------------------------------------------------------------*/
1301 /* assign asmOps to operand & result */
1302 aopOp (IC_LEFT (ic), ic, FALSE);
1303 aopOp (IC_RESULT (ic), ic, TRUE);
1305 /* if both are in bit space then
1307 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1308 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1311 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1312 emitcode ("cpl", "c");
1313 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1317 size = AOP_SIZE (IC_RESULT (ic));
1320 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1322 emitcode ("cpl", "a");
1323 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1328 /* release the aops */
1329 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1333 /*-----------------------------------------------------------------*/
1334 /* genUminusFloat - unary minus for floating points */
1335 /*-----------------------------------------------------------------*/
1337 genUminusFloat (operand * op, operand * result)
1339 int size, offset = 0;
1341 /* for this we just need to flip the
1342 first it then copy the rest in place */
1343 size = AOP_SIZE (op) - 1;
1344 l = aopGet (AOP (op), 3, FALSE, FALSE);
1348 emitcode ("cpl", "acc.7");
1349 aopPut (AOP (result), "a", 3);
1353 aopPut (AOP (result),
1354 aopGet (AOP (op), offset, FALSE, FALSE),
1360 /*-----------------------------------------------------------------*/
1361 /* genUminus - unary minus code generation */
1362 /*-----------------------------------------------------------------*/
1364 genUminus (iCode * ic)
1367 sym_link *optype, *rtype;
1371 aopOp (IC_LEFT (ic), ic, FALSE);
1372 aopOp (IC_RESULT (ic), ic, TRUE);
1374 /* if both in bit space then special
1376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1377 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1380 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1381 emitcode ("cpl", "c");
1382 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1386 optype = operandType (IC_LEFT (ic));
1387 rtype = operandType (IC_RESULT (ic));
1389 /* if float then do float stuff */
1390 if (IS_FLOAT (optype))
1392 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1396 /* otherwise subtract from zero */
1397 size = AOP_SIZE (IC_LEFT (ic));
1402 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1403 if (!strcmp (l, "a"))
1407 emitcode ("cpl", "a");
1408 emitcode ("addc", "a,#0");
1414 emitcode ("clr", "a");
1415 emitcode ("subb", "a,%s", l);
1417 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1420 /* if any remaining bytes in the result */
1421 /* we just need to propagate the sign */
1422 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1424 emitcode ("rlc", "a");
1425 emitcode ("subb", "a,acc");
1427 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1431 /* release the aops */
1432 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* saveRegisters - will look for a call and save the registers */
1438 /*-----------------------------------------------------------------*/
1440 saveRegisters (iCode * lic)
1447 for (ic = lic; ic; ic = ic->next)
1448 if (ic->op == CALL || ic->op == PCALL)
1453 fprintf (stderr, "found parameter push with no function call\n");
1457 /* if the registers have been saved already or don't need to be then
1459 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1460 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1463 /* find the registers in use at this time
1464 and push them away to safety */
1465 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1469 if (options.useXstack)
1471 if (bitVectBitValue (rsave, R0_IDX))
1472 emitcode ("mov", "b,r0");
1473 emitcode ("mov", "r0,%s", spname);
1474 for (i = 0; i < mcs51_nRegs; i++)
1476 if (bitVectBitValue (rsave, i))
1479 emitcode ("mov", "a,b");
1481 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1482 emitcode ("movx", "@r0,a");
1483 emitcode ("inc", "r0");
1486 emitcode ("mov", "%s,r0", spname);
1487 if (bitVectBitValue (rsave, R0_IDX))
1488 emitcode ("mov", "r0,b");
1491 for (i = 0; i < mcs51_nRegs; i++)
1493 if (bitVectBitValue (rsave, i))
1494 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1498 /*-----------------------------------------------------------------*/
1499 /* unsaveRegisters - pop the pushed registers */
1500 /*-----------------------------------------------------------------*/
1502 unsaveRegisters (iCode * ic)
1506 /* find the registers in use at this time
1507 and push them away to safety */
1508 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1511 if (options.useXstack)
1513 emitcode ("mov", "r0,%s", spname);
1514 for (i = mcs51_nRegs; i >= 0; i--)
1516 if (bitVectBitValue (rsave, i))
1518 emitcode ("dec", "r0");
1519 emitcode ("movx", "a,@r0");
1521 emitcode ("mov", "b,a");
1523 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1527 emitcode ("mov", "%s,r0", spname);
1528 if (bitVectBitValue (rsave, R0_IDX))
1529 emitcode ("mov", "r0,b");
1532 for (i = mcs51_nRegs; i >= 0; i--)
1534 if (bitVectBitValue (rsave, i))
1535 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1541 /*-----------------------------------------------------------------*/
1543 /*-----------------------------------------------------------------*/
1545 pushSide (operand * oper, int size)
1550 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1551 if (AOP_TYPE (oper) != AOP_REG &&
1552 AOP_TYPE (oper) != AOP_DIR &&
1555 emitcode ("mov", "a,%s", l);
1556 emitcode ("push", "acc");
1559 emitcode ("push", "%s", l);
1563 /*-----------------------------------------------------------------*/
1564 /* assignResultValue - */
1565 /*-----------------------------------------------------------------*/
1567 assignResultValue (operand * oper)
1570 int size = AOP_SIZE (oper);
1573 aopPut (AOP (oper), fReturn[offset], offset);
1579 /*-----------------------------------------------------------------*/
1580 /* genXpush - pushes onto the external stack */
1581 /*-----------------------------------------------------------------*/
1583 genXpush (iCode * ic)
1585 asmop *aop = newAsmop (0);
1587 int size, offset = 0;
1589 aopOp (IC_LEFT (ic), ic, FALSE);
1590 r = getFreePtr (ic, &aop, FALSE);
1593 emitcode ("mov", "%s,_spx", r->name);
1595 size = AOP_SIZE (IC_LEFT (ic));
1599 char *l = aopGet (AOP (IC_LEFT (ic)),
1600 offset++, FALSE, FALSE);
1602 emitcode ("movx", "@%s,a", r->name);
1603 emitcode ("inc", "%s", r->name);
1608 emitcode ("mov", "_spx,%s", r->name);
1610 freeAsmop (NULL, aop, ic, TRUE);
1611 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1614 /*-----------------------------------------------------------------*/
1615 /* genIpush - genrate code for pushing this gets a little complex */
1616 /*-----------------------------------------------------------------*/
1618 genIpush (iCode * ic)
1620 int size, offset = 0;
1623 D(emitcode (";", "genIpush"));
1625 /* if this is not a parm push : ie. it is spill push
1626 and spill push is always done on the local stack */
1630 /* and the item is spilt then do nothing */
1631 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1634 aopOp (IC_LEFT (ic), ic, FALSE);
1635 size = AOP_SIZE (IC_LEFT (ic));
1636 /* push it on the stack */
1639 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1645 emitcode ("push", "%s", l);
1650 /* this is a paramter push: in this case we call
1651 the routine to find the call and save those
1652 registers that need to be saved */
1655 /* if use external stack then call the external
1656 stack pushing routine */
1657 if (options.useXstack)
1663 /* then do the push */
1664 aopOp (IC_LEFT (ic), ic, FALSE);
1667 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1668 size = AOP_SIZE (IC_LEFT (ic));
1672 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1673 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1674 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1677 emitcode ("mov", "a,%s", l);
1678 emitcode ("push", "acc");
1681 emitcode ("push", "%s", l);
1684 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1687 /*-----------------------------------------------------------------*/
1688 /* genIpop - recover the registers: can happen only for spilling */
1689 /*-----------------------------------------------------------------*/
1691 genIpop (iCode * ic)
1696 /* if the temp was not pushed then */
1697 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1700 aopOp (IC_LEFT (ic), ic, FALSE);
1701 size = AOP_SIZE (IC_LEFT (ic));
1702 offset = (size - 1);
1704 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1707 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1710 /*-----------------------------------------------------------------*/
1711 /* unsaveRBank - restores the resgister bank from stack */
1712 /*-----------------------------------------------------------------*/
1714 unsaveRBank (int bank, iCode * ic, bool popPsw)
1720 if (options.useXstack)
1724 /* Assume r0 is available for use. */
1725 r = mcs51_regWithIdx (R0_IDX);;
1730 r = getFreePtr (ic, &aop, FALSE);
1732 emitcode ("mov", "%s,_spx", r->name);
1737 if (options.useXstack)
1739 emitcode ("movx", "a,@%s", r->name);
1740 emitcode ("mov", "psw,a");
1741 emitcode ("dec", "%s", r->name);
1745 emitcode ("pop", "psw");
1749 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1751 if (options.useXstack)
1753 emitcode ("movx", "a,@%s", r->name);
1754 emitcode ("mov", "(%s+%d),a",
1755 regs8051[i].base, 8 * bank + regs8051[i].offset);
1756 emitcode ("dec", "%s", r->name);
1760 emitcode ("pop", "(%s+%d)",
1761 regs8051[i].base, 8 * bank + regs8051[i].offset);
1764 if (options.useXstack)
1766 emitcode ("mov", "_spx,%s", r->name);
1771 freeAsmop (NULL, aop, ic, TRUE);
1775 /*-----------------------------------------------------------------*/
1776 /* saveRBank - saves an entire register bank on the stack */
1777 /*-----------------------------------------------------------------*/
1779 saveRBank (int bank, iCode * ic, bool pushPsw)
1785 if (options.useXstack)
1789 /* Assume r0 is available for use. */
1790 r = mcs51_regWithIdx (R0_IDX);;
1795 r = getFreePtr (ic, &aop, FALSE);
1797 emitcode ("mov", "%s,_spx", r->name);
1800 for (i = 0; i < mcs51_nRegs; i++)
1802 if (options.useXstack)
1804 emitcode ("inc", "%s", r->name);
1805 emitcode ("mov", "a,(%s+%d)",
1806 regs8051[i].base, 8 * bank + regs8051[i].offset);
1807 emitcode ("movx", "@%s,a", r->name);
1810 emitcode ("push", "(%s+%d)",
1811 regs8051[i].base, 8 * bank + regs8051[i].offset);
1816 if (options.useXstack)
1818 emitcode ("mov", "a,psw");
1819 emitcode ("movx", "@%s,a", r->name);
1820 emitcode ("inc", "%s", r->name);
1821 emitcode ("mov", "_spx,%s", r->name);
1826 emitcode ("push", "psw");
1829 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1834 freeAsmop (NULL, aop, ic, TRUE);
1843 /*-----------------------------------------------------------------*/
1844 /* genCall - generates a call statement */
1845 /*-----------------------------------------------------------------*/
1847 genCall (iCode * ic)
1850 bool restoreBank = FALSE;
1851 bool swapBanks = FALSE;
1853 D(emitcode(";", "genCall"));
1854 /* if send set is not empty the assign */
1859 for (sic = setFirstItem (_G.sendSet); sic;
1860 sic = setNextItem (_G.sendSet))
1862 int size, offset = 0;
1863 aopOp (IC_LEFT (sic), sic, FALSE);
1864 size = AOP_SIZE (IC_LEFT (sic));
1867 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1869 if (strcmp (l, fReturn[offset]))
1870 emitcode ("mov", "%s,%s",
1875 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1880 /* if we are calling a not _naked function that is not using
1881 the same register bank then we need to save the
1882 destination registers on the stack */
1883 dtype = operandType (IC_LEFT (ic));
1884 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1885 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1886 IFFUNC_ISISR (currFunc->type))
1890 /* This is unexpected; the bank should have been saved in
1893 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1899 /* if caller saves & we have not saved then */
1905 emitcode ("mov", "psw,#0x%02x",
1906 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1910 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1911 OP_SYMBOL (IC_LEFT (ic))->rname :
1912 OP_SYMBOL (IC_LEFT (ic))->name));
1916 emitcode ("mov", "psw,#0x%02x",
1917 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1920 /* if we need assign a result value */
1921 if ((IS_ITEMP (IC_RESULT (ic)) &&
1922 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1923 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1924 IS_TRUE_SYMOP (IC_RESULT (ic)))
1928 aopOp (IC_RESULT (ic), ic, FALSE);
1931 assignResultValue (IC_RESULT (ic));
1933 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1936 /* adjust the stack for parameters if
1941 if (ic->parmBytes > 3)
1943 emitcode ("mov", "a,%s", spname);
1944 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1945 emitcode ("mov", "%s,a", spname);
1948 for (i = 0; i < ic->parmBytes; i++)
1949 emitcode ("dec", "%s", spname);
1952 /* if we hade saved some registers then unsave them */
1953 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1954 unsaveRegisters (ic);
1956 /* if register bank was saved then pop them */
1958 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1961 /*-----------------------------------------------------------------*/
1962 /* genPcall - generates a call by pointer statement */
1963 /*-----------------------------------------------------------------*/
1965 genPcall (iCode * ic)
1968 symbol *rlbl = newiTempLabel (NULL);
1971 /* if caller saves & we have not saved then */
1975 /* if we are calling a function that is not using
1976 the same register bank then we need to save the
1977 destination registers on the stack */
1978 dtype = operandType (IC_LEFT (ic));
1980 IFFUNC_ISISR (currFunc->type) &&
1981 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
1982 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
1985 /* push the return address on to the stack */
1986 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1987 emitcode ("push", "acc");
1988 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1989 emitcode ("push", "acc");
1991 /* now push the calling address */
1992 aopOp (IC_LEFT (ic), ic, FALSE);
1994 pushSide (IC_LEFT (ic), FPTRSIZE);
1996 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1998 /* if send set is not empty the assign */
2003 for (sic = setFirstItem (_G.sendSet); sic;
2004 sic = setNextItem (_G.sendSet))
2006 int size, offset = 0;
2007 aopOp (IC_LEFT (sic), sic, FALSE);
2008 size = AOP_SIZE (IC_LEFT (sic));
2011 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2013 if (strcmp (l, fReturn[offset]))
2014 emitcode ("mov", "%s,%s",
2019 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2024 emitcode ("ret", "");
2025 emitcode ("", "%05d$:", (rlbl->key + 100));
2028 /* if we need assign a result value */
2029 if ((IS_ITEMP (IC_RESULT (ic)) &&
2030 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2031 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2032 IS_TRUE_SYMOP (IC_RESULT (ic)))
2036 aopOp (IC_RESULT (ic), ic, FALSE);
2039 assignResultValue (IC_RESULT (ic));
2041 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2044 /* adjust the stack for parameters if
2049 if (ic->parmBytes > 3)
2051 emitcode ("mov", "a,%s", spname);
2052 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2053 emitcode ("mov", "%s,a", spname);
2056 for (i = 0; i < ic->parmBytes; i++)
2057 emitcode ("dec", "%s", spname);
2061 /* if register bank was saved then unsave them */
2063 (FUNC_REGBANK (currFunc->type) !=
2064 FUNC_REGBANK (dtype)))
2065 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2067 /* if we hade saved some registers then
2070 unsaveRegisters (ic);
2073 /*-----------------------------------------------------------------*/
2074 /* resultRemat - result is rematerializable */
2075 /*-----------------------------------------------------------------*/
2077 resultRemat (iCode * ic)
2079 if (SKIP_IC (ic) || ic->op == IFX)
2082 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2084 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2085 if (sym->remat && !POINTER_SET (ic))
2092 #if defined(__BORLANDC__) || defined(_MSC_VER)
2093 #define STRCASECMP stricmp
2095 #define STRCASECMP strcasecmp
2098 /*-----------------------------------------------------------------*/
2099 /* inExcludeList - return 1 if the string is in exclude Reg list */
2100 /*-----------------------------------------------------------------*/
2102 inExcludeList (char *s)
2106 if (options.excludeRegs[i] &&
2107 STRCASECMP (options.excludeRegs[i], "none") == 0)
2110 for (i = 0; options.excludeRegs[i]; i++)
2112 if (options.excludeRegs[i] &&
2113 STRCASECMP (s, options.excludeRegs[i]) == 0)
2119 /*-----------------------------------------------------------------*/
2120 /* genFunction - generated code for function entry */
2121 /*-----------------------------------------------------------------*/
2123 genFunction (iCode * ic)
2127 bool switchedPSW = FALSE;
2130 /* create the function header */
2131 emitcode (";", "-----------------------------------------");
2132 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2133 emitcode (";", "-----------------------------------------");
2135 emitcode ("", "%s:", sym->rname);
2136 ftype = operandType (IC_LEFT (ic));
2138 if (IFFUNC_ISNAKED(ftype))
2140 emitcode(";", "naked function: no prologue.");
2144 /* if critical function then turn interrupts off */
2145 if (IFFUNC_ISCRITICAL (ftype))
2146 emitcode ("clr", "ea");
2148 /* here we need to generate the equates for the
2149 register bank if required */
2150 if (FUNC_REGBANK (ftype) != rbank)
2154 rbank = FUNC_REGBANK (ftype);
2155 for (i = 0; i < mcs51_nRegs; i++)
2157 if (strcmp (regs8051[i].base, "0") == 0)
2158 emitcode ("", "%s = 0x%02x",
2160 8 * rbank + regs8051[i].offset);
2162 emitcode ("", "%s = %s + 0x%02x",
2165 8 * rbank + regs8051[i].offset);
2169 /* if this is an interrupt service routine then
2170 save acc, b, dpl, dph */
2171 if (IFFUNC_ISISR (sym->type))
2174 if (!inExcludeList ("acc"))
2175 emitcode ("push", "acc");
2176 if (!inExcludeList ("b"))
2177 emitcode ("push", "b");
2178 if (!inExcludeList ("dpl"))
2179 emitcode ("push", "dpl");
2180 if (!inExcludeList ("dph"))
2181 emitcode ("push", "dph");
2182 /* if this isr has no bank i.e. is going to
2183 run with bank 0 , then we need to save more
2185 if (!FUNC_REGBANK (sym->type))
2188 /* if this function does not call any other
2189 function then we can be economical and
2190 save only those registers that are used */
2191 if (!IFFUNC_HASFCALL(sym->type))
2195 /* if any registers used */
2198 /* save the registers used */
2199 for (i = 0; i < sym->regsUsed->size; i++)
2201 if (bitVectBitValue (sym->regsUsed, i) ||
2202 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2203 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2210 /* this function has a function call cannot
2211 determines register usage so we will have to push the
2213 saveRBank (0, ic, FALSE);
2218 /* This ISR uses a non-zero bank.
2220 * We assume that the bank is available for our
2223 * However, if this ISR calls a function which uses some
2224 * other bank, we must save that bank entirely.
2226 unsigned long banksToSave = 0;
2228 if (IFFUNC_HASFCALL(sym->type))
2231 #define MAX_REGISTER_BANKS 4
2236 for (i = ic; i; i = i->next)
2238 if (i->op == ENDFUNCTION)
2240 /* we got to the end OK. */
2248 dtype = operandType (IC_LEFT(i));
2250 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2252 /* Mark this bank for saving. */
2253 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2255 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2259 banksToSave |= (1 << FUNC_REGBANK(dtype));
2262 /* And note that we don't need to do it in
2270 /* This is a mess; we have no idea what
2271 * register bank the called function might
2274 * The only thing I can think of to do is
2275 * throw a warning and hope.
2277 werror(W_FUNCPTR_IN_USING_ISR);
2281 if (banksToSave && options.useXstack)
2283 /* Since we aren't passing it an ic,
2284 * saveRBank will assume r0 is available to abuse.
2286 * So switch to our (trashable) bank now, so
2287 * the caller's R0 isn't trashed.
2289 emitcode ("push", "psw");
2290 emitcode ("mov", "psw,#0x%02x",
2291 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2295 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2297 if (banksToSave & (1 << ix))
2299 saveRBank(ix, NULL, FALSE);
2303 // jwk: this needs a closer look
2304 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2309 /* if callee-save to be used for this function
2310 then save the registers being used in this function */
2311 if (IFFUNC_CALLEESAVES(sym->type))
2315 /* if any registers used */
2318 /* save the registers used */
2319 for (i = 0; i < sym->regsUsed->size; i++)
2321 if (bitVectBitValue (sym->regsUsed, i) ||
2322 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2324 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2332 /* set the register bank to the desired value */
2333 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2336 emitcode ("push", "psw");
2337 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2340 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2343 if (options.useXstack)
2345 emitcode ("mov", "r0,%s", spname);
2346 emitcode ("mov", "a,_bp");
2347 emitcode ("movx", "@r0,a");
2348 emitcode ("inc", "%s", spname);
2352 /* set up the stack */
2353 emitcode ("push", "_bp"); /* save the callers stack */
2355 emitcode ("mov", "_bp,%s", spname);
2358 /* adjust the stack for the function */
2364 werror (W_STACK_OVERFLOW, sym->name);
2366 if (i > 3 && sym->recvSize < 4)
2369 emitcode ("mov", "a,sp");
2370 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2371 emitcode ("mov", "sp,a");
2376 emitcode ("inc", "sp");
2382 emitcode ("mov", "a,_spx");
2383 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2384 emitcode ("mov", "_spx,a");
2389 /*-----------------------------------------------------------------*/
2390 /* genEndFunction - generates epilogue for functions */
2391 /*-----------------------------------------------------------------*/
2393 genEndFunction (iCode * ic)
2395 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2397 if (IFFUNC_ISNAKED(sym->type))
2399 emitcode(";", "naked function: no epilogue.");
2403 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2405 emitcode ("mov", "%s,_bp", spname);
2408 /* if use external stack but some variables were
2409 added to the local stack then decrement the
2411 if (options.useXstack && sym->stack)
2413 emitcode ("mov", "a,sp");
2414 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2415 emitcode ("mov", "sp,a");
2419 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2421 if (options.useXstack)
2423 emitcode ("mov", "r0,%s", spname);
2424 emitcode ("movx", "a,@r0");
2425 emitcode ("mov", "_bp,a");
2426 emitcode ("dec", "%s", spname);
2430 emitcode ("pop", "_bp");
2434 /* restore the register bank */
2435 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2437 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2438 || !options.useXstack)
2440 /* Special case of ISR using non-zero bank with useXstack
2443 emitcode ("pop", "psw");
2447 if (IFFUNC_ISISR (sym->type))
2450 /* now we need to restore the registers */
2451 /* if this isr has no bank i.e. is going to
2452 run with bank 0 , then we need to save more
2454 if (!FUNC_REGBANK (sym->type))
2456 /* if this function does not call any other
2457 function then we can be economical and
2458 save only those registers that are used */
2459 if (!IFFUNC_HASFCALL(sym->type))
2463 /* if any registers used */
2466 /* save the registers used */
2467 for (i = sym->regsUsed->size; i >= 0; i--)
2469 if (bitVectBitValue (sym->regsUsed, i) ||
2470 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2471 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2478 /* this function has a function call cannot
2479 determines register usage so we will have to pop the
2481 unsaveRBank (0, ic, FALSE);
2486 /* This ISR uses a non-zero bank.
2488 * Restore any register banks saved by genFunction
2491 // jwk: this needs a closer look
2492 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2495 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2497 if (savedBanks & (1 << ix))
2499 unsaveRBank(ix, NULL, FALSE);
2503 if (options.useXstack)
2505 /* Restore bank AFTER calling unsaveRBank,
2506 * since it can trash r0.
2508 emitcode ("pop", "psw");
2512 if (!inExcludeList ("dph"))
2513 emitcode ("pop", "dph");
2514 if (!inExcludeList ("dpl"))
2515 emitcode ("pop", "dpl");
2516 if (!inExcludeList ("b"))
2517 emitcode ("pop", "b");
2518 if (!inExcludeList ("acc"))
2519 emitcode ("pop", "acc");
2521 if (IFFUNC_ISCRITICAL (sym->type))
2522 emitcode ("setb", "ea");
2524 /* if debug then send end of function */
2525 /* if (options.debug && currFunc) */
2526 if (options.debug && currFunc)
2529 emitcode ("", "C$%s$%d$%d$%d ==.",
2530 FileBaseName (ic->filename), currFunc->lastLine,
2531 ic->level, ic->block);
2532 if (IS_STATIC (currFunc->etype))
2533 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2535 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2539 emitcode ("reti", "");
2543 if (IFFUNC_ISCRITICAL (sym->type))
2544 emitcode ("setb", "ea");
2546 if (IFFUNC_CALLEESAVES(sym->type))
2550 /* if any registers used */
2553 /* save the registers used */
2554 for (i = sym->regsUsed->size; i >= 0; i--)
2556 if (bitVectBitValue (sym->regsUsed, i) ||
2557 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2558 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2564 /* if debug then send end of function */
2565 if (options.debug && currFunc)
2568 emitcode ("", "C$%s$%d$%d$%d ==.",
2569 FileBaseName (ic->filename), currFunc->lastLine,
2570 ic->level, ic->block);
2571 if (IS_STATIC (currFunc->etype))
2572 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2574 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2578 emitcode ("ret", "");
2583 /*-----------------------------------------------------------------*/
2584 /* genRet - generate code for return statement */
2585 /*-----------------------------------------------------------------*/
2589 int size, offset = 0, pushed = 0;
2591 /* if we have no return value then
2592 just generate the "ret" */
2596 /* we have something to return then
2597 move the return value into place */
2598 aopOp (IC_LEFT (ic), ic, FALSE);
2599 size = AOP_SIZE (IC_LEFT (ic));
2604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2607 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2609 emitcode ("push", "%s", l);
2614 l = aopGet (AOP (IC_LEFT (ic)), offset,
2616 if (strcmp (fReturn[offset], l))
2617 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2626 if (strcmp (fReturn[pushed], "a"))
2627 emitcode ("pop", fReturn[pushed]);
2629 emitcode ("pop", "acc");
2632 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2635 /* generate a jump to the return label
2636 if the next is not the return statement */
2637 if (!(ic->next && ic->next->op == LABEL &&
2638 IC_LABEL (ic->next) == returnLabel))
2640 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2644 /*-----------------------------------------------------------------*/
2645 /* genLabel - generates a label */
2646 /*-----------------------------------------------------------------*/
2648 genLabel (iCode * ic)
2650 /* special case never generate */
2651 if (IC_LABEL (ic) == entryLabel)
2654 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2657 /*-----------------------------------------------------------------*/
2658 /* genGoto - generates a ljmp */
2659 /*-----------------------------------------------------------------*/
2661 genGoto (iCode * ic)
2663 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2666 /*-----------------------------------------------------------------*/
2667 /* findLabelBackwards: walks back through the iCode chain looking */
2668 /* for the given label. Returns number of iCode instructions */
2669 /* between that label and given ic. */
2670 /* Returns zero if label not found. */
2671 /*-----------------------------------------------------------------*/
2673 findLabelBackwards (iCode * ic, int key)
2682 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2684 /* printf("findLabelBackwards = %d\n", count); */
2692 /*-----------------------------------------------------------------*/
2693 /* genPlusIncr :- does addition with increment if possible */
2694 /*-----------------------------------------------------------------*/
2696 genPlusIncr (iCode * ic)
2698 unsigned int icount;
2699 unsigned int size = getDataSize (IC_RESULT (ic));
2701 /* will try to generate an increment */
2702 /* if the right side is not a literal
2704 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2707 /* if the literal value of the right hand side
2708 is greater than 4 then it is not worth it */
2709 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2712 /* if increment 16 bits in register */
2713 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2721 /* If the next instruction is a goto and the goto target
2722 * is < 10 instructions previous to this, we can generate
2723 * jumps straight to that target.
2725 if (ic->next && ic->next->op == GOTO
2726 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2727 && labelRange <= 10)
2729 emitcode (";", "tail increment optimized");
2730 tlbl = IC_LABEL (ic->next);
2735 tlbl = newiTempLabel (NULL);
2738 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2739 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2740 IS_AOP_PREG (IC_RESULT (ic)))
2741 emitcode ("cjne", "%s,#0x00,%05d$"
2742 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2746 emitcode ("clr", "a");
2747 emitcode ("cjne", "a,%s,%05d$"
2748 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2752 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2755 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2756 IS_AOP_PREG (IC_RESULT (ic)))
2757 emitcode ("cjne", "%s,#0x00,%05d$"
2758 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2761 emitcode ("cjne", "a,%s,%05d$"
2762 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2765 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2769 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2770 IS_AOP_PREG (IC_RESULT (ic)))
2771 emitcode ("cjne", "%s,#0x00,%05d$"
2772 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2776 emitcode ("cjne", "a,%s,%05d$"
2777 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2780 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2785 emitcode ("", "%05d$:", tlbl->key + 100);
2790 /* if the sizes are greater than 1 then we cannot */
2791 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2792 AOP_SIZE (IC_LEFT (ic)) > 1)
2795 /* we can if the aops of the left & result match or
2796 if they are in registers and the registers are the
2798 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2803 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2804 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2805 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2811 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2820 /*-----------------------------------------------------------------*/
2821 /* outBitAcc - output a bit in acc */
2822 /*-----------------------------------------------------------------*/
2824 outBitAcc (operand * result)
2826 symbol *tlbl = newiTempLabel (NULL);
2827 /* if the result is a bit */
2828 if (AOP_TYPE (result) == AOP_CRY)
2830 aopPut (AOP (result), "a", 0);
2834 emitcode ("jz", "%05d$", tlbl->key + 100);
2835 emitcode ("mov", "a,%s", one);
2836 emitcode ("", "%05d$:", tlbl->key + 100);
2841 /*-----------------------------------------------------------------*/
2842 /* genPlusBits - generates code for addition of two bits */
2843 /*-----------------------------------------------------------------*/
2845 genPlusBits (iCode * ic)
2847 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2849 symbol *lbl = newiTempLabel (NULL);
2850 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2851 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2852 emitcode ("cpl", "c");
2853 emitcode ("", "%05d$:", (lbl->key + 100));
2854 outBitC (IC_RESULT (ic));
2858 emitcode ("clr", "a");
2859 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2860 emitcode ("rlc", "a");
2861 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2862 emitcode ("addc", "a,#0x00");
2863 outAcc (IC_RESULT (ic));
2868 /* This is the original version of this code.
2870 * This is being kept around for reference,
2871 * because I am not entirely sure I got it right...
2874 adjustArithmeticResult (iCode * ic)
2876 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2877 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2878 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2879 aopPut (AOP (IC_RESULT (ic)),
2880 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2883 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2884 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2885 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2886 aopPut (AOP (IC_RESULT (ic)),
2887 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2890 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2891 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2892 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2893 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2894 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2897 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2898 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2902 /* This is the pure and virtuous version of this code.
2903 * I'm pretty certain it's right, but not enough to toss the old
2907 adjustArithmeticResult (iCode * ic)
2909 if (opIsGptr (IC_RESULT (ic)) &&
2910 opIsGptr (IC_LEFT (ic)) &&
2911 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2913 aopPut (AOP (IC_RESULT (ic)),
2914 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2918 if (opIsGptr (IC_RESULT (ic)) &&
2919 opIsGptr (IC_RIGHT (ic)) &&
2920 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2922 aopPut (AOP (IC_RESULT (ic)),
2923 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2927 if (opIsGptr (IC_RESULT (ic)) &&
2928 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2929 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2930 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2931 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2934 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2935 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2940 /*-----------------------------------------------------------------*/
2941 /* genPlus - generates code for addition */
2942 /*-----------------------------------------------------------------*/
2944 genPlus (iCode * ic)
2946 int size, offset = 0;
2948 /* special cases :- */
2950 aopOp (IC_LEFT (ic), ic, FALSE);
2951 aopOp (IC_RIGHT (ic), ic, FALSE);
2952 aopOp (IC_RESULT (ic), ic, TRUE);
2954 /* if literal, literal on the right or
2955 if left requires ACC or right is already
2957 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2958 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2959 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2961 operand *t = IC_RIGHT (ic);
2962 IC_RIGHT (ic) = IC_LEFT (ic);
2966 /* if both left & right are in bit
2968 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2969 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2975 /* if left in bit space & right literal */
2976 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2977 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2979 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2980 /* if result in bit space */
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2983 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2984 emitcode ("cpl", "c");
2985 outBitC (IC_RESULT (ic));
2989 size = getDataSize (IC_RESULT (ic));
2992 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2993 emitcode ("addc", "a,#00");
2994 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3000 /* if I can do an increment instead
3001 of add then GOOD for ME */
3002 if (genPlusIncr (ic) == TRUE)
3005 size = getDataSize (IC_RESULT (ic));
3009 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3011 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3013 emitcode ("add", "a,%s",
3014 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3016 emitcode ("addc", "a,%s",
3017 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3021 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3023 emitcode ("add", "a,%s",
3024 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3026 emitcode ("addc", "a,%s",
3027 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3029 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3032 adjustArithmeticResult (ic);
3035 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3036 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3037 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3040 /*-----------------------------------------------------------------*/
3041 /* genMinusDec :- does subtraction with deccrement if possible */
3042 /*-----------------------------------------------------------------*/
3044 genMinusDec (iCode * ic)
3046 unsigned int icount;
3047 unsigned int size = getDataSize (IC_RESULT (ic));
3049 /* will try to generate an increment */
3050 /* if the right side is not a literal
3052 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3055 /* if the literal value of the right hand side
3056 is greater than 4 then it is not worth it */
3057 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3060 /* if decrement 16 bits in register */
3061 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3069 /* If the next instruction is a goto and the goto target
3070 * is <= 10 instructions previous to this, we can generate
3071 * jumps straight to that target.
3073 if (ic->next && ic->next->op == GOTO
3074 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3075 && labelRange <= 10)
3077 emitcode (";", "tail decrement optimized");
3078 tlbl = IC_LABEL (ic->next);
3083 tlbl = newiTempLabel (NULL);
3087 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3089 IS_AOP_PREG (IC_RESULT (ic)))
3090 emitcode ("cjne", "%s,#0xff,%05d$"
3091 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3095 emitcode ("mov", "a,#0xff");
3096 emitcode ("cjne", "a,%s,%05d$"
3097 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3100 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3103 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3104 IS_AOP_PREG (IC_RESULT (ic)))
3105 emitcode ("cjne", "%s,#0xff,%05d$"
3106 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3110 emitcode ("cjne", "a,%s,%05d$"
3111 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3114 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3118 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3119 IS_AOP_PREG (IC_RESULT (ic)))
3120 emitcode ("cjne", "%s,#0xff,%05d$"
3121 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3125 emitcode ("cjne", "a,%s,%05d$"
3126 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3129 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3133 emitcode ("", "%05d$:", tlbl->key + 100);
3138 /* if the sizes are greater than 1 then we cannot */
3139 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3140 AOP_SIZE (IC_LEFT (ic)) > 1)
3143 /* we can if the aops of the left & result match or
3144 if they are in registers and the registers are the
3146 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3150 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3158 /*-----------------------------------------------------------------*/
3159 /* addSign - complete with sign */
3160 /*-----------------------------------------------------------------*/
3162 addSign (operand * result, int offset, int sign)
3164 int size = (getDataSize (result) - offset);
3169 emitcode ("rlc", "a");
3170 emitcode ("subb", "a,acc");
3172 aopPut (AOP (result), "a", offset++);
3176 aopPut (AOP (result), zero, offset++);
3180 /*-----------------------------------------------------------------*/
3181 /* genMinusBits - generates code for subtraction of two bits */
3182 /*-----------------------------------------------------------------*/
3184 genMinusBits (iCode * ic)
3186 symbol *lbl = newiTempLabel (NULL);
3187 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3189 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3190 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3191 emitcode ("cpl", "c");
3192 emitcode ("", "%05d$:", (lbl->key + 100));
3193 outBitC (IC_RESULT (ic));
3197 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3198 emitcode ("subb", "a,acc");
3199 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3200 emitcode ("inc", "a");
3201 emitcode ("", "%05d$:", (lbl->key + 100));
3202 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3203 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3207 /*-----------------------------------------------------------------*/
3208 /* genMinus - generates code for subtraction */
3209 /*-----------------------------------------------------------------*/
3211 genMinus (iCode * ic)
3213 int size, offset = 0;
3214 unsigned long lit = 0L;
3216 aopOp (IC_LEFT (ic), ic, FALSE);
3217 aopOp (IC_RIGHT (ic), ic, FALSE);
3218 aopOp (IC_RESULT (ic), ic, TRUE);
3220 /* special cases :- */
3221 /* if both left & right are in bit space */
3222 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3223 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3229 /* if I can do an decrement instead
3230 of subtract then GOOD for ME */
3231 if (genMinusDec (ic) == TRUE)
3234 size = getDataSize (IC_RESULT (ic));
3236 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3242 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3246 /* if literal, add a,#-lit, else normal subb */
3249 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3250 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3251 emitcode ("subb", "a,%s",
3252 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3255 /* first add without previous c */
3257 if (!size && lit==-1) {
3258 emitcode ("dec", "a");
3260 emitcode ("add", "a,#0x%02x",
3261 (unsigned int) (lit & 0x0FFL));
3264 emitcode ("addc", "a,#0x%02x",
3265 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3268 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3271 adjustArithmeticResult (ic);
3274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3275 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3276 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3280 /*-----------------------------------------------------------------*/
3281 /* genMultbits :- multiplication of bits */
3282 /*-----------------------------------------------------------------*/
3284 genMultbits (operand * left,
3288 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3289 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3294 /*-----------------------------------------------------------------*/
3295 /* genMultOneByte : 8*8=8/16 bit multiplication */
3296 /*-----------------------------------------------------------------*/
3298 genMultOneByte (operand * left,
3302 sym_link *opetype = operandType (result);
3304 int size=AOP_SIZE(result);
3306 if (size<1 || size>2) {
3307 // this should never happen
3308 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3309 AOP_SIZE(result), __FILE__, lineno);
3313 /* (if two literals: the value is computed before) */
3314 /* if one literal, literal on the right */
3315 if (AOP_TYPE (left) == AOP_LIT)
3320 //emitcode (";", "swapped left and right");
3323 if (SPEC_USIGN(opetype)
3324 // ignore the sign of left and right, what else can we do?
3325 || (SPEC_USIGN(operandType(left)) &&
3326 SPEC_USIGN(operandType(right)))) {
3327 // just an unsigned 8*8=8/16 multiply
3328 //emitcode (";","unsigned");
3329 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3330 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3331 emitcode ("mul", "ab");
3332 aopPut (AOP (result), "a", 0);
3334 aopPut (AOP (result), "b", 1);
3339 // we have to do a signed multiply
3341 //emitcode (";", "signed");
3342 emitcode ("clr", "F0"); // reset sign flag
3343 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3345 lbl=newiTempLabel(NULL);
3346 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3347 // left side is negative, 8-bit two's complement, this fails for -128
3348 emitcode ("setb", "F0"); // set sign flag
3349 emitcode ("cpl", "a");
3350 emitcode ("inc", "a");
3352 emitcode ("", "%05d$:", lbl->key+100);
3355 if (AOP_TYPE(right)==AOP_LIT) {
3356 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3357 /* AND literal negative */
3359 emitcode ("cpl", "F0"); // complement sign flag
3360 emitcode ("mov", "b,#0x%02x", -val);
3362 emitcode ("mov", "b,#0x%02x", val);
3365 lbl=newiTempLabel(NULL);
3366 emitcode ("mov", "b,a");
3367 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3368 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3369 // right side is negative, 8-bit two's complement
3370 emitcode ("cpl", "F0"); // complement sign flag
3371 emitcode ("cpl", "a");
3372 emitcode ("inc", "a");
3373 emitcode ("", "%05d$:", lbl->key+100);
3375 emitcode ("mul", "ab");
3377 lbl=newiTempLabel(NULL);
3378 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3379 // only ONE op was negative, we have to do a 8/16-bit two's complement
3380 emitcode ("cpl", "a"); // lsb
3382 emitcode ("inc", "a");
3384 emitcode ("add", "a,#1");
3385 emitcode ("xch", "a,b");
3386 emitcode ("cpl", "a"); // msb
3387 emitcode ("addc", "a,#0");
3388 emitcode ("xch", "a,b");
3391 emitcode ("", "%05d$:", lbl->key+100);
3392 aopPut (AOP (result), "a", 0);
3394 aopPut (AOP (result), "b", 1);
3398 /*-----------------------------------------------------------------*/
3399 /* genMult - generates code for multiplication */
3400 /*-----------------------------------------------------------------*/
3402 genMult (iCode * ic)
3404 operand *left = IC_LEFT (ic);
3405 operand *right = IC_RIGHT (ic);
3406 operand *result = IC_RESULT (ic);
3408 /* assign the amsops */
3409 aopOp (left, ic, FALSE);
3410 aopOp (right, ic, FALSE);
3411 aopOp (result, ic, TRUE);
3413 /* special cases first */
3415 if (AOP_TYPE (left) == AOP_CRY &&
3416 AOP_TYPE (right) == AOP_CRY)
3418 genMultbits (left, right, result);
3422 /* if both are of size == 1 */
3423 if (AOP_SIZE (left) == 1 &&
3424 AOP_SIZE (right) == 1)
3426 genMultOneByte (left, right, result);
3430 /* should have been converted to function call */
3434 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3435 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3436 freeAsmop (result, NULL, ic, TRUE);
3439 /*-----------------------------------------------------------------*/
3440 /* genDivbits :- division of bits */
3441 /*-----------------------------------------------------------------*/
3443 genDivbits (operand * left,
3450 /* the result must be bit */
3451 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3452 l = aopGet (AOP (left), 0, FALSE, FALSE);
3456 emitcode ("div", "ab");
3457 emitcode ("rrc", "a");
3458 aopPut (AOP (result), "c", 0);
3461 /*-----------------------------------------------------------------*/
3462 /* genDivOneByte : 8 bit division */
3463 /*-----------------------------------------------------------------*/
3465 genDivOneByte (operand * left,
3469 sym_link *opetype = operandType (result);
3474 size = AOP_SIZE (result) - 1;
3476 /* signed or unsigned */
3477 if (SPEC_USIGN (opetype))
3479 /* unsigned is easy */
3480 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3481 l = aopGet (AOP (left), 0, FALSE, FALSE);
3483 emitcode ("div", "ab");
3484 aopPut (AOP (result), "a", 0);
3486 aopPut (AOP (result), zero, offset++);
3490 /* signed is a little bit more difficult */
3492 /* save the signs of the operands */
3493 l = aopGet (AOP (left), 0, FALSE, FALSE);
3495 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3496 emitcode ("push", "acc"); /* save it on the stack */
3498 /* now sign adjust for both left & right */
3499 l = aopGet (AOP (right), 0, FALSE, FALSE);
3501 lbl = newiTempLabel (NULL);
3502 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3503 emitcode ("cpl", "a");
3504 emitcode ("inc", "a");
3505 emitcode ("", "%05d$:", (lbl->key + 100));
3506 emitcode ("mov", "b,a");
3508 /* sign adjust left side */
3509 l = aopGet (AOP (left), 0, FALSE, FALSE);
3512 lbl = newiTempLabel (NULL);
3513 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3514 emitcode ("cpl", "a");
3515 emitcode ("inc", "a");
3516 emitcode ("", "%05d$:", (lbl->key + 100));
3518 /* now the division */
3519 emitcode ("div", "ab");
3520 /* we are interested in the lower order
3522 emitcode ("mov", "b,a");
3523 lbl = newiTempLabel (NULL);
3524 emitcode ("pop", "acc");
3525 /* if there was an over flow we don't
3526 adjust the sign of the result */
3527 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3528 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3530 emitcode ("clr", "a");
3531 emitcode ("subb", "a,b");
3532 emitcode ("mov", "b,a");
3533 emitcode ("", "%05d$:", (lbl->key + 100));
3535 /* now we are done */
3536 aopPut (AOP (result), "b", 0);
3539 emitcode ("mov", "c,b.7");
3540 emitcode ("subb", "a,acc");
3543 aopPut (AOP (result), "a", offset++);
3547 /*-----------------------------------------------------------------*/
3548 /* genDiv - generates code for division */
3549 /*-----------------------------------------------------------------*/
3553 operand *left = IC_LEFT (ic);
3554 operand *right = IC_RIGHT (ic);
3555 operand *result = IC_RESULT (ic);
3557 /* assign the amsops */
3558 aopOp (left, ic, FALSE);
3559 aopOp (right, ic, FALSE);
3560 aopOp (result, ic, TRUE);
3562 /* special cases first */
3564 if (AOP_TYPE (left) == AOP_CRY &&
3565 AOP_TYPE (right) == AOP_CRY)
3567 genDivbits (left, right, result);
3571 /* if both are of size == 1 */
3572 if (AOP_SIZE (left) == 1 &&
3573 AOP_SIZE (right) == 1)
3575 genDivOneByte (left, right, result);
3579 /* should have been converted to function call */
3582 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3583 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3584 freeAsmop (result, NULL, ic, TRUE);
3587 /*-----------------------------------------------------------------*/
3588 /* genModbits :- modulus of bits */
3589 /*-----------------------------------------------------------------*/
3591 genModbits (operand * left,
3598 /* the result must be bit */
3599 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3600 l = aopGet (AOP (left), 0, FALSE, FALSE);
3604 emitcode ("div", "ab");
3605 emitcode ("mov", "a,b");
3606 emitcode ("rrc", "a");
3607 aopPut (AOP (result), "c", 0);
3610 /*-----------------------------------------------------------------*/
3611 /* genModOneByte : 8 bit modulus */
3612 /*-----------------------------------------------------------------*/
3614 genModOneByte (operand * left,
3618 sym_link *opetype = operandType (result);
3622 /* signed or unsigned */
3623 if (SPEC_USIGN (opetype))
3625 /* unsigned is easy */
3626 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3627 l = aopGet (AOP (left), 0, FALSE, FALSE);
3629 emitcode ("div", "ab");
3630 aopPut (AOP (result), "b", 0);
3634 /* signed is a little bit more difficult */
3636 /* save the signs of the operands */
3637 l = aopGet (AOP (left), 0, FALSE, FALSE);
3640 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3641 emitcode ("push", "acc"); /* save it on the stack */
3643 /* now sign adjust for both left & right */
3644 l = aopGet (AOP (right), 0, FALSE, FALSE);
3647 lbl = newiTempLabel (NULL);
3648 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3649 emitcode ("cpl", "a");
3650 emitcode ("inc", "a");
3651 emitcode ("", "%05d$:", (lbl->key + 100));
3652 emitcode ("mov", "b,a");
3654 /* sign adjust left side */
3655 l = aopGet (AOP (left), 0, FALSE, FALSE);
3658 lbl = newiTempLabel (NULL);
3659 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3660 emitcode ("cpl", "a");
3661 emitcode ("inc", "a");
3662 emitcode ("", "%05d$:", (lbl->key + 100));
3664 /* now the multiplication */
3665 emitcode ("div", "ab");
3666 /* we are interested in the lower order
3668 lbl = newiTempLabel (NULL);
3669 emitcode ("pop", "acc");
3670 /* if there was an over flow we don't
3671 adjust the sign of the result */
3672 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3673 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3675 emitcode ("clr", "a");
3676 emitcode ("subb", "a,b");
3677 emitcode ("mov", "b,a");
3678 emitcode ("", "%05d$:", (lbl->key + 100));
3680 /* now we are done */
3681 aopPut (AOP (result), "b", 0);
3685 /*-----------------------------------------------------------------*/
3686 /* genMod - generates code for division */
3687 /*-----------------------------------------------------------------*/
3691 operand *left = IC_LEFT (ic);
3692 operand *right = IC_RIGHT (ic);
3693 operand *result = IC_RESULT (ic);
3695 /* assign the amsops */
3696 aopOp (left, ic, FALSE);
3697 aopOp (right, ic, FALSE);
3698 aopOp (result, ic, TRUE);
3700 /* special cases first */
3702 if (AOP_TYPE (left) == AOP_CRY &&
3703 AOP_TYPE (right) == AOP_CRY)
3705 genModbits (left, right, result);
3709 /* if both are of size == 1 */
3710 if (AOP_SIZE (left) == 1 &&
3711 AOP_SIZE (right) == 1)
3713 genModOneByte (left, right, result);
3717 /* should have been converted to function call */
3721 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3722 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3723 freeAsmop (result, NULL, ic, TRUE);
3726 /*-----------------------------------------------------------------*/
3727 /* genIfxJump :- will create a jump depending on the ifx */
3728 /*-----------------------------------------------------------------*/
3730 genIfxJump (iCode * ic, char *jval)
3733 symbol *tlbl = newiTempLabel (NULL);
3736 /* if true label then we jump if condition
3740 jlbl = IC_TRUE (ic);
3741 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3742 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3746 /* false label is present */
3747 jlbl = IC_FALSE (ic);
3748 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3749 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3751 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3752 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3754 emitcode (inst, "%05d$", tlbl->key + 100);
3755 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3756 emitcode ("", "%05d$:", tlbl->key + 100);
3758 /* mark the icode as generated */
3762 /*-----------------------------------------------------------------*/
3763 /* genCmp :- greater or less than comparison */
3764 /*-----------------------------------------------------------------*/
3766 genCmp (operand * left, operand * right,
3767 operand * result, iCode * ifx, int sign, iCode *ic)
3769 int size, offset = 0;
3770 unsigned long lit = 0L;
3772 /* if left & right are bit variables */
3773 if (AOP_TYPE (left) == AOP_CRY &&
3774 AOP_TYPE (right) == AOP_CRY)
3776 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3777 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3781 /* subtract right from left if at the
3782 end the carry flag is set then we know that
3783 left is greater than right */
3784 size = max (AOP_SIZE (left), AOP_SIZE (right));
3786 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3787 if ((size == 1) && !sign &&
3788 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3790 symbol *lbl = newiTempLabel (NULL);
3791 emitcode ("cjne", "%s,%s,%05d$",
3792 aopGet (AOP (left), offset, FALSE, FALSE),
3793 aopGet (AOP (right), offset, FALSE, FALSE),
3795 emitcode ("", "%05d$:", lbl->key + 100);
3799 if (AOP_TYPE (right) == AOP_LIT)
3801 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3802 /* optimize if(x < 0) or if(x >= 0) */
3811 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3812 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3814 genIfxJump (ifx, "acc.7");
3818 emitcode ("rlc", "a");
3826 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3827 if (sign && size == 0)
3829 emitcode ("xrl", "a,#0x80");
3830 if (AOP_TYPE (right) == AOP_LIT)
3832 unsigned long lit = (unsigned long)
3833 floatFromVal (AOP (right)->aopu.aop_lit);
3834 emitcode ("subb", "a,#0x%02x",
3835 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3839 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3840 emitcode ("xrl", "b,#0x80");
3841 emitcode ("subb", "a,b");
3845 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3853 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3859 /* if the result is used in the next
3860 ifx conditional branch then generate
3861 code a little differently */
3863 genIfxJump (ifx, "c");
3866 /* leave the result in acc */
3870 /*-----------------------------------------------------------------*/
3871 /* genCmpGt :- greater than comparison */
3872 /*-----------------------------------------------------------------*/
3874 genCmpGt (iCode * ic, iCode * ifx)
3876 operand *left, *right, *result;
3877 sym_link *letype, *retype;
3880 left = IC_LEFT (ic);
3881 right = IC_RIGHT (ic);
3882 result = IC_RESULT (ic);
3884 letype = getSpec (operandType (left));
3885 retype = getSpec (operandType (right));
3886 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3887 /* assign the amsops */
3888 aopOp (left, ic, FALSE);
3889 aopOp (right, ic, FALSE);
3890 aopOp (result, ic, TRUE);
3892 genCmp (right, left, result, ifx, sign,ic);
3894 freeAsmop (result, NULL, ic, TRUE);
3897 /*-----------------------------------------------------------------*/
3898 /* genCmpLt - less than comparisons */
3899 /*-----------------------------------------------------------------*/
3901 genCmpLt (iCode * ic, iCode * ifx)
3903 operand *left, *right, *result;
3904 sym_link *letype, *retype;
3907 left = IC_LEFT (ic);
3908 right = IC_RIGHT (ic);
3909 result = IC_RESULT (ic);
3911 letype = getSpec (operandType (left));
3912 retype = getSpec (operandType (right));
3913 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3915 /* assign the amsops */
3916 aopOp (left, ic, FALSE);
3917 aopOp (right, ic, FALSE);
3918 aopOp (result, ic, TRUE);
3920 genCmp (left, right, result, ifx, sign,ic);
3922 freeAsmop (result, NULL, ic, TRUE);
3925 /*-----------------------------------------------------------------*/
3926 /* gencjneshort - compare and jump if not equal */
3927 /*-----------------------------------------------------------------*/
3929 gencjneshort (operand * left, operand * right, symbol * lbl)
3931 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3933 unsigned long lit = 0L;
3935 /* if the left side is a literal or
3936 if the right is in a pointer register and left
3938 if ((AOP_TYPE (left) == AOP_LIT) ||
3939 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3945 if (AOP_TYPE (right) == AOP_LIT)
3946 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3948 /* if the right side is a literal then anything goes */
3949 if (AOP_TYPE (right) == AOP_LIT &&
3950 AOP_TYPE (left) != AOP_DIR)
3954 emitcode ("cjne", "%s,%s,%05d$",
3955 aopGet (AOP (left), offset, FALSE, FALSE),
3956 aopGet (AOP (right), offset, FALSE, FALSE),
3962 /* if the right side is in a register or in direct space or
3963 if the left is a pointer register & right is not */
3964 else if (AOP_TYPE (right) == AOP_REG ||
3965 AOP_TYPE (right) == AOP_DIR ||
3966 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3967 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3971 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3972 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3973 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3974 emitcode ("jnz", "%05d$", lbl->key + 100);
3976 emitcode ("cjne", "a,%s,%05d$",
3977 aopGet (AOP (right), offset, FALSE, TRUE),
3984 /* right is a pointer reg need both a & b */
3987 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3988 if (strcmp (l, "b"))
3989 emitcode ("mov", "b,%s", l);
3990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3991 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3997 /*-----------------------------------------------------------------*/
3998 /* gencjne - compare and jump if not equal */
3999 /*-----------------------------------------------------------------*/
4001 gencjne (operand * left, operand * right, symbol * lbl)
4003 symbol *tlbl = newiTempLabel (NULL);
4005 gencjneshort (left, right, lbl);
4007 emitcode ("mov", "a,%s", one);
4008 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4009 emitcode ("", "%05d$:", lbl->key + 100);
4010 emitcode ("clr", "a");
4011 emitcode ("", "%05d$:", tlbl->key + 100);
4014 /*-----------------------------------------------------------------*/
4015 /* genCmpEq - generates code for equal to */
4016 /*-----------------------------------------------------------------*/
4018 genCmpEq (iCode * ic, iCode * ifx)
4020 operand *left, *right, *result;
4022 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4023 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4024 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4026 /* if literal, literal on the right or
4027 if the right is in a pointer register and left
4029 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4030 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4032 operand *t = IC_RIGHT (ic);
4033 IC_RIGHT (ic) = IC_LEFT (ic);
4037 if (ifx && !AOP_SIZE (result))
4040 /* if they are both bit variables */
4041 if (AOP_TYPE (left) == AOP_CRY &&
4042 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4044 if (AOP_TYPE (right) == AOP_LIT)
4046 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4049 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4050 emitcode ("cpl", "c");
4054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4058 emitcode ("clr", "c");
4060 /* AOP_TYPE(right) == AOP_CRY */
4064 symbol *lbl = newiTempLabel (NULL);
4065 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4066 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4067 emitcode ("cpl", "c");
4068 emitcode ("", "%05d$:", (lbl->key + 100));
4070 /* if true label then we jump if condition
4072 tlbl = newiTempLabel (NULL);
4075 emitcode ("jnc", "%05d$", tlbl->key + 100);
4076 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4080 emitcode ("jc", "%05d$", tlbl->key + 100);
4081 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4083 emitcode ("", "%05d$:", tlbl->key + 100);
4087 tlbl = newiTempLabel (NULL);
4088 gencjneshort (left, right, tlbl);
4091 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4092 emitcode ("", "%05d$:", tlbl->key + 100);
4096 symbol *lbl = newiTempLabel (NULL);
4097 emitcode ("sjmp", "%05d$", lbl->key + 100);
4098 emitcode ("", "%05d$:", tlbl->key + 100);
4099 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4100 emitcode ("", "%05d$:", lbl->key + 100);
4103 /* mark the icode as generated */
4108 /* if they are both bit variables */
4109 if (AOP_TYPE (left) == AOP_CRY &&
4110 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4117 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4118 emitcode ("cpl", "c");
4122 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4126 emitcode ("clr", "c");
4128 /* AOP_TYPE(right) == AOP_CRY */
4132 symbol *lbl = newiTempLabel (NULL);
4133 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4134 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4135 emitcode ("cpl", "c");
4136 emitcode ("", "%05d$:", (lbl->key + 100));
4139 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4146 genIfxJump (ifx, "c");
4149 /* if the result is used in an arithmetic operation
4150 then put the result in place */
4155 gencjne (left, right, newiTempLabel (NULL));
4156 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4158 aopPut (AOP (result), "a", 0);
4163 genIfxJump (ifx, "a");
4166 /* if the result is used in an arithmetic operation
4167 then put the result in place */
4168 if (AOP_TYPE (result) != AOP_CRY)
4170 /* leave the result in acc */
4174 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4175 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4176 freeAsmop (result, NULL, ic, TRUE);
4179 /*-----------------------------------------------------------------*/
4180 /* ifxForOp - returns the icode containing the ifx for operand */
4181 /*-----------------------------------------------------------------*/
4183 ifxForOp (operand * op, iCode * ic)
4185 /* if true symbol then needs to be assigned */
4186 if (IS_TRUE_SYMOP (op))
4189 /* if this has register type condition and
4190 the next instruction is ifx with the same operand
4191 and live to of the operand is upto the ifx only then */
4193 ic->next->op == IFX &&
4194 IC_COND (ic->next)->key == op->key &&
4195 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4201 /*-----------------------------------------------------------------*/
4202 /* hasInc - operand is incremented before any other use */
4203 /*-----------------------------------------------------------------*/
4205 hasInc (operand *op, iCode *ic)
4207 sym_link *type = operandType(op);
4208 sym_link *retype = getSpec (type);
4209 iCode *lic = ic->next;
4212 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4213 if (!IS_SYMOP(op)) return NULL;
4215 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4216 isize = getSize(type->next);
4218 /* if operand of the form op = op + <sizeof *op> */
4219 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4220 isOperandEqual(IC_RESULT(lic),op) &&
4221 isOperandLiteral(IC_RIGHT(lic)) &&
4222 operandLitValue(IC_RIGHT(lic)) == isize) {
4225 /* if the operand used or deffed */
4226 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4234 /*-----------------------------------------------------------------*/
4235 /* genAndOp - for && operation */
4236 /*-----------------------------------------------------------------*/
4238 genAndOp (iCode * ic)
4240 operand *left, *right, *result;
4243 /* note here that && operations that are in an
4244 if statement are taken away by backPatchLabels
4245 only those used in arthmetic operations remain */
4246 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4247 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4248 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4250 /* if both are bit variables */
4251 if (AOP_TYPE (left) == AOP_CRY &&
4252 AOP_TYPE (right) == AOP_CRY)
4254 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4255 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4260 tlbl = newiTempLabel (NULL);
4262 emitcode ("jz", "%05d$", tlbl->key + 100);
4264 emitcode ("", "%05d$:", tlbl->key + 100);
4268 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4270 freeAsmop (result, NULL, ic, TRUE);
4274 /*-----------------------------------------------------------------*/
4275 /* genOrOp - for || operation */
4276 /*-----------------------------------------------------------------*/
4278 genOrOp (iCode * ic)
4280 operand *left, *right, *result;
4283 /* note here that || operations that are in an
4284 if statement are taken away by backPatchLabels
4285 only those used in arthmetic operations remain */
4286 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4287 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4288 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4290 /* if both are bit variables */
4291 if (AOP_TYPE (left) == AOP_CRY &&
4292 AOP_TYPE (right) == AOP_CRY)
4294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4295 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4300 tlbl = newiTempLabel (NULL);
4302 emitcode ("jnz", "%05d$", tlbl->key + 100);
4304 emitcode ("", "%05d$:", tlbl->key + 100);
4308 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4310 freeAsmop (result, NULL, ic, TRUE);
4313 /*-----------------------------------------------------------------*/
4314 /* isLiteralBit - test if lit == 2^n */
4315 /*-----------------------------------------------------------------*/
4317 isLiteralBit (unsigned long lit)
4319 unsigned long pw[32] =
4320 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4321 0x100L, 0x200L, 0x400L, 0x800L,
4322 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4323 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4324 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4325 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4326 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4329 for (idx = 0; idx < 32; idx++)
4335 /*-----------------------------------------------------------------*/
4336 /* continueIfTrue - */
4337 /*-----------------------------------------------------------------*/
4339 continueIfTrue (iCode * ic)
4342 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4346 /*-----------------------------------------------------------------*/
4348 /*-----------------------------------------------------------------*/
4350 jumpIfTrue (iCode * ic)
4353 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4357 /*-----------------------------------------------------------------*/
4358 /* jmpTrueOrFalse - */
4359 /*-----------------------------------------------------------------*/
4361 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4363 // ugly but optimized by peephole
4366 symbol *nlbl = newiTempLabel (NULL);
4367 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4368 emitcode ("", "%05d$:", tlbl->key + 100);
4369 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4370 emitcode ("", "%05d$:", nlbl->key + 100);
4374 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4375 emitcode ("", "%05d$:", tlbl->key + 100);
4380 /*-----------------------------------------------------------------*/
4381 /* genAnd - code for and */
4382 /*-----------------------------------------------------------------*/
4384 genAnd (iCode * ic, iCode * ifx)
4386 operand *left, *right, *result;
4387 int size, offset = 0;
4388 unsigned long lit = 0L;
4392 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4393 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4394 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4397 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4399 AOP_TYPE (left), AOP_TYPE (right));
4400 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4402 AOP_SIZE (left), AOP_SIZE (right));
4405 /* if left is a literal & right is not then exchange them */
4406 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4407 AOP_NEEDSACC (left))
4409 operand *tmp = right;
4414 /* if result = right then exchange them */
4415 if (sameRegs (AOP (result), AOP (right)))
4417 operand *tmp = right;
4422 /* if right is bit then exchange them */
4423 if (AOP_TYPE (right) == AOP_CRY &&
4424 AOP_TYPE (left) != AOP_CRY)
4426 operand *tmp = right;
4430 if (AOP_TYPE (right) == AOP_LIT)
4431 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4433 size = AOP_SIZE (result);
4436 // result = bit & yy;
4437 if (AOP_TYPE (left) == AOP_CRY)
4439 // c = bit & literal;
4440 if (AOP_TYPE (right) == AOP_LIT)
4444 if (size && sameRegs (AOP (result), AOP (left)))
4447 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4452 if (size && (AOP_TYPE (result) == AOP_CRY))
4454 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4457 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4462 emitcode ("clr", "c");
4467 if (AOP_TYPE (right) == AOP_CRY)
4470 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4471 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4476 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4478 emitcode ("rrc", "a");
4479 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4487 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4488 genIfxJump (ifx, "c");
4492 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4493 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4494 if ((AOP_TYPE (right) == AOP_LIT) &&
4495 (AOP_TYPE (result) == AOP_CRY) &&
4496 (AOP_TYPE (left) != AOP_CRY))
4498 int posbit = isLiteralBit (lit);
4503 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4506 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4512 sprintf (buffer, "acc.%d", posbit & 0x07);
4513 genIfxJump (ifx, buffer);
4520 symbol *tlbl = newiTempLabel (NULL);
4521 int sizel = AOP_SIZE (left);
4523 emitcode ("setb", "c");
4526 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4528 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4530 if ((posbit = isLiteralBit (bytelit)) != 0)
4531 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4534 if (bytelit != 0x0FFL)
4535 emitcode ("anl", "a,%s",
4536 aopGet (AOP (right), offset, FALSE, TRUE));
4537 emitcode ("jnz", "%05d$", tlbl->key + 100);
4542 // bit = left & literal
4545 emitcode ("clr", "c");
4546 emitcode ("", "%05d$:", tlbl->key + 100);
4548 // if(left & literal)
4552 jmpTrueOrFalse (ifx, tlbl);
4560 /* if left is same as result */
4561 if (sameRegs (AOP (result), AOP (left)))
4563 for (; size--; offset++)
4565 if (AOP_TYPE (right) == AOP_LIT)
4567 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4569 else if (bytelit == 0)
4570 aopPut (AOP (result), zero, offset);
4571 else if (IS_AOP_PREG (result))
4573 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4574 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4575 aopPut (AOP (result), "a", offset);
4578 emitcode ("anl", "%s,%s",
4579 aopGet (AOP (left), offset, FALSE, TRUE),
4580 aopGet (AOP (right), offset, FALSE, FALSE));
4584 if (AOP_TYPE (left) == AOP_ACC)
4585 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4588 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4589 if (IS_AOP_PREG (result))
4591 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4592 aopPut (AOP (result), "a", offset);
4596 emitcode ("anl", "%s,a",
4597 aopGet (AOP (left), offset, FALSE, TRUE));
4604 // left & result in different registers
4605 if (AOP_TYPE (result) == AOP_CRY)
4608 // if(size), result in bit
4609 // if(!size && ifx), conditional oper: if(left & right)
4610 symbol *tlbl = newiTempLabel (NULL);
4611 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4613 emitcode ("setb", "c");
4616 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4617 emitcode ("anl", "a,%s",
4618 aopGet (AOP (right), offset, FALSE, FALSE));
4620 if (AOP_TYPE(left)==AOP_ACC) {
4621 emitcode("mov", "b,a");
4622 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4623 emitcode("anl", "a,b");
4625 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4626 emitcode ("anl", "a,%s",
4627 aopGet (AOP (left), offset, FALSE, FALSE));
4630 emitcode ("jnz", "%05d$", tlbl->key + 100);
4636 emitcode ("", "%05d$:", tlbl->key + 100);
4640 jmpTrueOrFalse (ifx, tlbl);
4644 for (; (size--); offset++)
4647 // result = left & right
4648 if (AOP_TYPE (right) == AOP_LIT)
4650 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4652 aopPut (AOP (result),
4653 aopGet (AOP (left), offset, FALSE, FALSE),
4657 else if (bytelit == 0)
4659 aopPut (AOP (result), zero, offset);
4663 // faster than result <- left, anl result,right
4664 // and better if result is SFR
4665 if (AOP_TYPE (left) == AOP_ACC)
4666 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4670 emitcode ("anl", "a,%s",
4671 aopGet (AOP (left), offset, FALSE, FALSE));
4673 aopPut (AOP (result), "a", offset);
4679 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4681 freeAsmop (result, NULL, ic, TRUE);
4684 /*-----------------------------------------------------------------*/
4685 /* genOr - code for or */
4686 /*-----------------------------------------------------------------*/
4688 genOr (iCode * ic, iCode * ifx)
4690 operand *left, *right, *result;
4691 int size, offset = 0;
4692 unsigned long lit = 0L;
4694 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4695 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4696 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4699 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4701 AOP_TYPE (left), AOP_TYPE (right));
4702 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4704 AOP_SIZE (left), AOP_SIZE (right));
4707 /* if left is a literal & right is not then exchange them */
4708 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4709 AOP_NEEDSACC (left))
4711 operand *tmp = right;
4716 /* if result = right then exchange them */
4717 if (sameRegs (AOP (result), AOP (right)))
4719 operand *tmp = right;
4724 /* if right is bit then exchange them */
4725 if (AOP_TYPE (right) == AOP_CRY &&
4726 AOP_TYPE (left) != AOP_CRY)
4728 operand *tmp = right;
4732 if (AOP_TYPE (right) == AOP_LIT)
4733 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4735 size = AOP_SIZE (result);
4739 if (AOP_TYPE (left) == AOP_CRY)
4741 if (AOP_TYPE (right) == AOP_LIT)
4743 // c = bit & literal;
4746 // lit != 0 => result = 1
4747 if (AOP_TYPE (result) == AOP_CRY)
4750 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4752 continueIfTrue (ifx);
4755 emitcode ("setb", "c");
4759 // lit == 0 => result = left
4760 if (size && sameRegs (AOP (result), AOP (left)))
4762 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4767 if (AOP_TYPE (right) == AOP_CRY)
4770 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4771 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4776 symbol *tlbl = newiTempLabel (NULL);
4777 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4778 emitcode ("setb", "c");
4779 emitcode ("jb", "%s,%05d$",
4780 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4782 emitcode ("jnz", "%05d$", tlbl->key + 100);
4783 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4785 jmpTrueOrFalse (ifx, tlbl);
4791 emitcode ("", "%05d$:", tlbl->key + 100);
4800 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4801 genIfxJump (ifx, "c");
4805 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4806 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4807 if ((AOP_TYPE (right) == AOP_LIT) &&
4808 (AOP_TYPE (result) == AOP_CRY) &&
4809 (AOP_TYPE (left) != AOP_CRY))
4815 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4817 continueIfTrue (ifx);
4822 // lit = 0, result = boolean(left)
4824 emitcode ("setb", "c");
4828 symbol *tlbl = newiTempLabel (NULL);
4829 emitcode ("jnz", "%05d$", tlbl->key + 100);
4831 emitcode ("", "%05d$:", tlbl->key + 100);
4835 genIfxJump (ifx, "a");
4843 /* if left is same as result */
4844 if (sameRegs (AOP (result), AOP (left)))
4846 for (; size--; offset++)
4848 if (AOP_TYPE (right) == AOP_LIT)
4850 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4852 else if (IS_AOP_PREG (left))
4854 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4855 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4856 aopPut (AOP (result), "a", offset);
4859 emitcode ("orl", "%s,%s",
4860 aopGet (AOP (left), offset, FALSE, TRUE),
4861 aopGet (AOP (right), offset, FALSE, FALSE));
4865 if (AOP_TYPE (left) == AOP_ACC)
4866 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4869 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4870 if (IS_AOP_PREG (left))
4872 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4873 aopPut (AOP (result), "a", offset);
4876 emitcode ("orl", "%s,a",
4877 aopGet (AOP (left), offset, FALSE, TRUE));
4884 // left & result in different registers
4885 if (AOP_TYPE (result) == AOP_CRY)
4888 // if(size), result in bit
4889 // if(!size && ifx), conditional oper: if(left | right)
4890 symbol *tlbl = newiTempLabel (NULL);
4891 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4893 emitcode ("setb", "c");
4896 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4897 emitcode ("orl", "a,%s",
4898 aopGet (AOP (right), offset, FALSE, FALSE));
4900 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4901 emitcode ("orl", "a,%s",
4902 aopGet (AOP (left), offset, FALSE, FALSE));
4904 emitcode ("jnz", "%05d$", tlbl->key + 100);
4910 emitcode ("", "%05d$:", tlbl->key + 100);
4914 jmpTrueOrFalse (ifx, tlbl);
4917 for (; (size--); offset++)
4920 // result = left & right
4921 if (AOP_TYPE (right) == AOP_LIT)
4923 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4925 aopPut (AOP (result),
4926 aopGet (AOP (left), offset, FALSE, FALSE),
4931 // faster than result <- left, anl result,right
4932 // and better if result is SFR
4933 if (AOP_TYPE (left) == AOP_ACC)
4934 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4937 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4938 emitcode ("orl", "a,%s",
4939 aopGet (AOP (left), offset, FALSE, FALSE));
4941 aopPut (AOP (result), "a", offset);
4946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 freeAsmop (result, NULL, ic, TRUE);
4951 /*-----------------------------------------------------------------*/
4952 /* genXor - code for xclusive or */
4953 /*-----------------------------------------------------------------*/
4955 genXor (iCode * ic, iCode * ifx)
4957 operand *left, *right, *result;
4958 int size, offset = 0;
4959 unsigned long lit = 0L;
4961 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4962 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4963 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4966 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4968 AOP_TYPE (left), AOP_TYPE (right));
4969 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4971 AOP_SIZE (left), AOP_SIZE (right));
4974 /* if left is a literal & right is not ||
4975 if left needs acc & right does not */
4976 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4977 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4979 operand *tmp = right;
4984 /* if result = right then exchange them */
4985 if (sameRegs (AOP (result), AOP (right)))
4987 operand *tmp = right;
4992 /* if right is bit then exchange them */
4993 if (AOP_TYPE (right) == AOP_CRY &&
4994 AOP_TYPE (left) != AOP_CRY)
4996 operand *tmp = right;
5000 if (AOP_TYPE (right) == AOP_LIT)
5001 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5003 size = AOP_SIZE (result);
5007 if (AOP_TYPE (left) == AOP_CRY)
5009 if (AOP_TYPE (right) == AOP_LIT)
5011 // c = bit & literal;
5014 // lit>>1 != 0 => result = 1
5015 if (AOP_TYPE (result) == AOP_CRY)
5018 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5020 continueIfTrue (ifx);
5023 emitcode ("setb", "c");
5030 // lit == 0, result = left
5031 if (size && sameRegs (AOP (result), AOP (left)))
5033 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5037 // lit == 1, result = not(left)
5038 if (size && sameRegs (AOP (result), AOP (left)))
5040 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5045 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5046 emitcode ("cpl", "c");
5055 symbol *tlbl = newiTempLabel (NULL);
5056 if (AOP_TYPE (right) == AOP_CRY)
5059 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5063 int sizer = AOP_SIZE (right);
5065 // if val>>1 != 0, result = 1
5066 emitcode ("setb", "c");
5069 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5071 // test the msb of the lsb
5072 emitcode ("anl", "a,#0xfe");
5073 emitcode ("jnz", "%05d$", tlbl->key + 100);
5077 emitcode ("rrc", "a");
5079 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5080 emitcode ("cpl", "c");
5081 emitcode ("", "%05d$:", (tlbl->key + 100));
5088 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5089 genIfxJump (ifx, "c");
5093 if (sameRegs (AOP (result), AOP (left)))
5095 /* if left is same as result */
5096 for (; size--; offset++)
5098 if (AOP_TYPE (right) == AOP_LIT)
5100 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5102 else if (IS_AOP_PREG (left))
5104 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5105 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5106 aopPut (AOP (result), "a", offset);
5109 emitcode ("xrl", "%s,%s",
5110 aopGet (AOP (left), offset, FALSE, TRUE),
5111 aopGet (AOP (right), offset, FALSE, FALSE));
5115 if (AOP_TYPE (left) == AOP_ACC)
5116 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5119 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5120 if (IS_AOP_PREG (left))
5122 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5123 aopPut (AOP (result), "a", offset);
5126 emitcode ("xrl", "%s,a",
5127 aopGet (AOP (left), offset, FALSE, TRUE));
5134 // left & result in different registers
5135 if (AOP_TYPE (result) == AOP_CRY)
5138 // if(size), result in bit
5139 // if(!size && ifx), conditional oper: if(left ^ right)
5140 symbol *tlbl = newiTempLabel (NULL);
5141 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5143 emitcode ("setb", "c");
5146 if ((AOP_TYPE (right) == AOP_LIT) &&
5147 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5149 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5153 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5154 emitcode ("xrl", "a,%s",
5155 aopGet (AOP (right), offset, FALSE, FALSE));
5157 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5158 emitcode ("xrl", "a,%s",
5159 aopGet (AOP (left), offset, FALSE, FALSE));
5162 emitcode ("jnz", "%05d$", tlbl->key + 100);
5168 emitcode ("", "%05d$:", tlbl->key + 100);
5172 jmpTrueOrFalse (ifx, tlbl);
5175 for (; (size--); offset++)
5178 // result = left & right
5179 if (AOP_TYPE (right) == AOP_LIT)
5181 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5183 aopPut (AOP (result),
5184 aopGet (AOP (left), offset, FALSE, FALSE),
5189 // faster than result <- left, anl result,right
5190 // and better if result is SFR
5191 if (AOP_TYPE (left) == AOP_ACC)
5192 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5195 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5196 emitcode ("xrl", "a,%s",
5197 aopGet (AOP (left), offset, FALSE, TRUE));
5199 aopPut (AOP (result), "a", offset);
5204 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 freeAsmop (result, NULL, ic, TRUE);
5209 /*-----------------------------------------------------------------*/
5210 /* genInline - write the inline code out */
5211 /*-----------------------------------------------------------------*/
5213 genInline (iCode * ic)
5215 char *buffer, *bp, *bp1;
5217 _G.inLine += (!options.asmpeep);
5219 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5220 strcpy (buffer, IC_INLINE (ic));
5222 /* emit each line as a code */
5247 /* emitcode("",buffer); */
5248 _G.inLine -= (!options.asmpeep);
5251 /*-----------------------------------------------------------------*/
5252 /* genRRC - rotate right with carry */
5253 /*-----------------------------------------------------------------*/
5257 operand *left, *result;
5258 int size, offset = 0;
5261 /* rotate right with carry */
5262 left = IC_LEFT (ic);
5263 result = IC_RESULT (ic);
5264 aopOp (left, ic, FALSE);
5265 aopOp (result, ic, FALSE);
5267 /* move it to the result */
5268 size = AOP_SIZE (result);
5270 if (size == 1) { /* special case for 1 byte */
5271 l = aopGet (AOP (left), offset, FALSE, FALSE);
5273 emitcode ("rr", "a");
5279 l = aopGet (AOP (left), offset, FALSE, FALSE);
5281 emitcode ("rrc", "a");
5282 if (AOP_SIZE (result) > 1)
5283 aopPut (AOP (result), "a", offset--);
5285 /* now we need to put the carry into the
5286 highest order byte of the result */
5287 if (AOP_SIZE (result) > 1)
5289 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5292 emitcode ("mov", "acc.7,c");
5294 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5295 freeAsmop (left, NULL, ic, TRUE);
5296 freeAsmop (result, NULL, ic, TRUE);
5299 /*-----------------------------------------------------------------*/
5300 /* genRLC - generate code for rotate left with carry */
5301 /*-----------------------------------------------------------------*/
5305 operand *left, *result;
5306 int size, offset = 0;
5309 /* rotate right with carry */
5310 left = IC_LEFT (ic);
5311 result = IC_RESULT (ic);
5312 aopOp (left, ic, FALSE);
5313 aopOp (result, ic, FALSE);
5315 /* move it to the result */
5316 size = AOP_SIZE (result);
5320 l = aopGet (AOP (left), offset, FALSE, FALSE);
5322 if (size == 0) { /* special case for 1 byte */
5326 emitcode ("add", "a,acc");
5327 if (AOP_SIZE (result) > 1)
5328 aopPut (AOP (result), "a", offset++);
5331 l = aopGet (AOP (left), offset, FALSE, FALSE);
5333 emitcode ("rlc", "a");
5334 if (AOP_SIZE (result) > 1)
5335 aopPut (AOP (result), "a", offset++);
5338 /* now we need to put the carry into the
5339 highest order byte of the result */
5340 if (AOP_SIZE (result) > 1)
5342 l = aopGet (AOP (result), 0, FALSE, FALSE);
5345 emitcode ("mov", "acc.0,c");
5347 aopPut (AOP (result), "a", 0);
5348 freeAsmop (left, NULL, ic, TRUE);
5349 freeAsmop (result, NULL, ic, TRUE);
5352 /*-----------------------------------------------------------------*/
5353 /* genGetHbit - generates code get highest order bit */
5354 /*-----------------------------------------------------------------*/
5356 genGetHbit (iCode * ic)
5358 operand *left, *result;
5359 left = IC_LEFT (ic);
5360 result = IC_RESULT (ic);
5361 aopOp (left, ic, FALSE);
5362 aopOp (result, ic, FALSE);
5364 /* get the highest order byte into a */
5365 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5366 if (AOP_TYPE (result) == AOP_CRY)
5368 emitcode ("rlc", "a");
5373 emitcode ("rl", "a");
5374 emitcode ("anl", "a,#0x01");
5379 freeAsmop (left, NULL, ic, TRUE);
5380 freeAsmop (result, NULL, ic, TRUE);
5383 /*-----------------------------------------------------------------*/
5384 /* AccRol - rotate left accumulator by known count */
5385 /*-----------------------------------------------------------------*/
5387 AccRol (int shCount)
5389 shCount &= 0x0007; // shCount : 0..7
5396 emitcode ("rl", "a");
5399 emitcode ("rl", "a");
5400 emitcode ("rl", "a");
5403 emitcode ("swap", "a");
5404 emitcode ("rr", "a");
5407 emitcode ("swap", "a");
5410 emitcode ("swap", "a");
5411 emitcode ("rl", "a");
5414 emitcode ("rr", "a");
5415 emitcode ("rr", "a");
5418 emitcode ("rr", "a");
5423 /*-----------------------------------------------------------------*/
5424 /* AccLsh - left shift accumulator by known count */
5425 /*-----------------------------------------------------------------*/
5427 AccLsh (int shCount)
5432 emitcode ("add", "a,acc");
5433 else if (shCount == 2)
5435 emitcode ("add", "a,acc");
5436 emitcode ("add", "a,acc");
5440 /* rotate left accumulator */
5442 /* and kill the lower order bits */
5443 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5448 /*-----------------------------------------------------------------*/
5449 /* AccRsh - right shift accumulator by known count */
5450 /*-----------------------------------------------------------------*/
5452 AccRsh (int shCount)
5459 emitcode ("rrc", "a");
5463 /* rotate right accumulator */
5464 AccRol (8 - shCount);
5465 /* and kill the higher order bits */
5466 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5471 /*-----------------------------------------------------------------*/
5472 /* AccSRsh - signed right shift accumulator by known count */
5473 /*-----------------------------------------------------------------*/
5475 AccSRsh (int shCount)
5482 emitcode ("mov", "c,acc.7");
5483 emitcode ("rrc", "a");
5485 else if (shCount == 2)
5487 emitcode ("mov", "c,acc.7");
5488 emitcode ("rrc", "a");
5489 emitcode ("mov", "c,acc.7");
5490 emitcode ("rrc", "a");
5494 tlbl = newiTempLabel (NULL);
5495 /* rotate right accumulator */
5496 AccRol (8 - shCount);
5497 /* and kill the higher order bits */
5498 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5499 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5500 emitcode ("orl", "a,#0x%02x",
5501 (unsigned char) ~SRMask[shCount]);
5502 emitcode ("", "%05d$:", tlbl->key + 100);
5507 /*-----------------------------------------------------------------*/
5508 /* shiftR1Left2Result - shift right one byte from left to result */
5509 /*-----------------------------------------------------------------*/
5511 shiftR1Left2Result (operand * left, int offl,
5512 operand * result, int offr,
5513 int shCount, int sign)
5515 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5516 /* shift right accumulator */
5521 aopPut (AOP (result), "a", offr);
5524 /*-----------------------------------------------------------------*/
5525 /* shiftL1Left2Result - shift left one byte from left to result */
5526 /*-----------------------------------------------------------------*/
5528 shiftL1Left2Result (operand * left, int offl,
5529 operand * result, int offr, int shCount)
5532 l = aopGet (AOP (left), offl, FALSE, FALSE);
5534 /* shift left accumulator */
5536 aopPut (AOP (result), "a", offr);
5539 /*-----------------------------------------------------------------*/
5540 /* movLeft2Result - move byte from left to result */
5541 /*-----------------------------------------------------------------*/
5543 movLeft2Result (operand * left, int offl,
5544 operand * result, int offr, int sign)
5547 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5549 l = aopGet (AOP (left), offl, FALSE, FALSE);
5551 if (*l == '@' && (IS_AOP_PREG (result)))
5553 emitcode ("mov", "a,%s", l);
5554 aopPut (AOP (result), "a", offr);
5559 aopPut (AOP (result), l, offr);
5562 /* MSB sign in acc.7 ! */
5563 if (getDataSize (left) == offl + 1)
5565 emitcode ("mov", "a,%s", l);
5566 aopPut (AOP (result), "a", offr);
5573 /*-----------------------------------------------------------------*/
5574 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5575 /*-----------------------------------------------------------------*/
5579 emitcode ("rrc", "a");
5580 emitcode ("xch", "a,%s", x);
5581 emitcode ("rrc", "a");
5582 emitcode ("xch", "a,%s", x);
5585 /*-----------------------------------------------------------------*/
5586 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5587 /*-----------------------------------------------------------------*/
5591 emitcode ("xch", "a,%s", x);
5592 emitcode ("rlc", "a");
5593 emitcode ("xch", "a,%s", x);
5594 emitcode ("rlc", "a");
5597 /*-----------------------------------------------------------------*/
5598 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5599 /*-----------------------------------------------------------------*/
5603 emitcode ("xch", "a,%s", x);
5604 emitcode ("add", "a,acc");
5605 emitcode ("xch", "a,%s", x);
5606 emitcode ("rlc", "a");
5609 /*-----------------------------------------------------------------*/
5610 /* AccAXLsh - left shift a:x by known count (0..7) */
5611 /*-----------------------------------------------------------------*/
5613 AccAXLsh (char *x, int shCount)
5628 case 5: // AAAAABBB:CCCCCDDD
5630 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5632 emitcode ("anl", "a,#0x%02x",
5633 SLMask[shCount]); // BBB00000:CCCCCDDD
5635 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5637 AccRol (shCount); // DDDCCCCC:BBB00000
5639 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5641 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5643 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5645 emitcode ("anl", "a,#0x%02x",
5646 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5648 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5650 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5653 case 6: // AAAAAABB:CCCCCCDD
5654 emitcode ("anl", "a,#0x%02x",
5655 SRMask[shCount]); // 000000BB:CCCCCCDD
5656 emitcode ("mov", "c,acc.0"); // c = B
5657 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5659 AccAXRrl1 (x); // BCCCCCCD:D000000B
5660 AccAXRrl1 (x); // BBCCCCCC:DD000000
5662 emitcode("rrc","a");
5663 emitcode("xch","a,%s", x);
5664 emitcode("rrc","a");
5665 emitcode("mov","c,acc.0"); //<< get correct bit
5666 emitcode("xch","a,%s", x);
5668 emitcode("rrc","a");
5669 emitcode("xch","a,%s", x);
5670 emitcode("rrc","a");
5671 emitcode("xch","a,%s", x);
5674 case 7: // a:x <<= 7
5676 emitcode ("anl", "a,#0x%02x",
5677 SRMask[shCount]); // 0000000B:CCCCCCCD
5679 emitcode ("mov", "c,acc.0"); // c = B
5681 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5683 AccAXRrl1 (x); // BCCCCCCC:D0000000
5691 /*-----------------------------------------------------------------*/
5692 /* AccAXRsh - right shift a:x known count (0..7) */
5693 /*-----------------------------------------------------------------*/
5695 AccAXRsh (char *x, int shCount)
5703 AccAXRrl1 (x); // 0->a:x
5708 AccAXRrl1 (x); // 0->a:x
5711 AccAXRrl1 (x); // 0->a:x
5716 case 5: // AAAAABBB:CCCCCDDD = a:x
5718 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5720 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5722 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5724 emitcode ("anl", "a,#0x%02x",
5725 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5727 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5729 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5731 emitcode ("anl", "a,#0x%02x",
5732 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5734 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5736 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5738 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5741 case 6: // AABBBBBB:CCDDDDDD
5743 emitcode ("mov", "c,acc.7");
5744 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5746 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5748 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5750 emitcode ("anl", "a,#0x%02x",
5751 SRMask[shCount]); // 000000AA:BBBBBBCC
5754 case 7: // ABBBBBBB:CDDDDDDD
5756 emitcode ("mov", "c,acc.7"); // c = A
5758 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5760 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5762 emitcode ("anl", "a,#0x%02x",
5763 SRMask[shCount]); // 0000000A:BBBBBBBC
5771 /*-----------------------------------------------------------------*/
5772 /* AccAXRshS - right shift signed a:x known count (0..7) */
5773 /*-----------------------------------------------------------------*/
5775 AccAXRshS (char *x, int shCount)
5783 emitcode ("mov", "c,acc.7");
5784 AccAXRrl1 (x); // s->a:x
5788 emitcode ("mov", "c,acc.7");
5789 AccAXRrl1 (x); // s->a:x
5791 emitcode ("mov", "c,acc.7");
5792 AccAXRrl1 (x); // s->a:x
5797 case 5: // AAAAABBB:CCCCCDDD = a:x
5799 tlbl = newiTempLabel (NULL);
5800 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5802 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5804 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5806 emitcode ("anl", "a,#0x%02x",
5807 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5809 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5811 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5813 emitcode ("anl", "a,#0x%02x",
5814 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5816 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5818 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5820 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5822 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5823 emitcode ("orl", "a,#0x%02x",
5824 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5826 emitcode ("", "%05d$:", tlbl->key + 100);
5827 break; // SSSSAAAA:BBBCCCCC
5829 case 6: // AABBBBBB:CCDDDDDD
5831 tlbl = newiTempLabel (NULL);
5832 emitcode ("mov", "c,acc.7");
5833 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5835 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5837 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5839 emitcode ("anl", "a,#0x%02x",
5840 SRMask[shCount]); // 000000AA:BBBBBBCC
5842 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5843 emitcode ("orl", "a,#0x%02x",
5844 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5846 emitcode ("", "%05d$:", tlbl->key + 100);
5848 case 7: // ABBBBBBB:CDDDDDDD
5850 tlbl = newiTempLabel (NULL);
5851 emitcode ("mov", "c,acc.7"); // c = A
5853 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5855 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5857 emitcode ("anl", "a,#0x%02x",
5858 SRMask[shCount]); // 0000000A:BBBBBBBC
5860 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5861 emitcode ("orl", "a,#0x%02x",
5862 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5864 emitcode ("", "%05d$:", tlbl->key + 100);
5871 /*-----------------------------------------------------------------*/
5872 /* shiftL2Left2Result - shift left two bytes from left to result */
5873 /*-----------------------------------------------------------------*/
5875 shiftL2Left2Result (operand * left, int offl,
5876 operand * result, int offr, int shCount)
5878 if (sameRegs (AOP (result), AOP (left)) &&
5879 ((offl + MSB16) == offr))
5881 /* don't crash result[offr] */
5882 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5883 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5887 movLeft2Result (left, offl, result, offr, 0);
5888 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5890 /* ax << shCount (x = lsb(result)) */
5891 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5892 aopPut (AOP (result), "a", offr + MSB16);
5896 /*-----------------------------------------------------------------*/
5897 /* shiftR2Left2Result - shift right two bytes from left to result */
5898 /*-----------------------------------------------------------------*/
5900 shiftR2Left2Result (operand * left, int offl,
5901 operand * result, int offr,
5902 int shCount, int sign)
5904 if (sameRegs (AOP (result), AOP (left)) &&
5905 ((offl + MSB16) == offr))
5907 /* don't crash result[offr] */
5908 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5909 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5913 movLeft2Result (left, offl, result, offr, 0);
5914 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5916 /* a:x >> shCount (x = lsb(result)) */
5918 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5920 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5921 if (getDataSize (result) > 1)
5922 aopPut (AOP (result), "a", offr + MSB16);
5925 /*-----------------------------------------------------------------*/
5926 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5927 /*-----------------------------------------------------------------*/
5929 shiftLLeftOrResult (operand * left, int offl,
5930 operand * result, int offr, int shCount)
5932 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5933 /* shift left accumulator */
5935 /* or with result */
5936 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5937 /* back to result */
5938 aopPut (AOP (result), "a", offr);
5941 /*-----------------------------------------------------------------*/
5942 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5943 /*-----------------------------------------------------------------*/
5945 shiftRLeftOrResult (operand * left, int offl,
5946 operand * result, int offr, int shCount)
5948 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5949 /* shift right accumulator */
5951 /* or with result */
5952 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5953 /* back to result */
5954 aopPut (AOP (result), "a", offr);
5957 /*-----------------------------------------------------------------*/
5958 /* genlshOne - left shift a one byte quantity by known count */
5959 /*-----------------------------------------------------------------*/
5961 genlshOne (operand * result, operand * left, int shCount)
5963 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5966 /*-----------------------------------------------------------------*/
5967 /* genlshTwo - left shift two bytes by known amount != 0 */
5968 /*-----------------------------------------------------------------*/
5970 genlshTwo (operand * result, operand * left, int shCount)
5974 size = getDataSize (result);
5976 /* if shCount >= 8 */
5984 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5986 movLeft2Result (left, LSB, result, MSB16, 0);
5988 aopPut (AOP (result), zero, LSB);
5991 /* 1 <= shCount <= 7 */
5995 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5997 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6001 /*-----------------------------------------------------------------*/
6002 /* shiftLLong - shift left one long from left to result */
6003 /* offl = LSB or MSB16 */
6004 /*-----------------------------------------------------------------*/
6006 shiftLLong (operand * left, operand * result, int offr)
6009 int size = AOP_SIZE (result);
6011 if (size >= LSB + offr)
6013 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6015 emitcode ("add", "a,acc");
6016 if (sameRegs (AOP (left), AOP (result)) &&
6017 size >= MSB16 + offr && offr != LSB)
6018 emitcode ("xch", "a,%s",
6019 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6021 aopPut (AOP (result), "a", LSB + offr);
6024 if (size >= MSB16 + offr)
6026 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6028 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6031 emitcode ("rlc", "a");
6032 if (sameRegs (AOP (left), AOP (result)) &&
6033 size >= MSB24 + offr && offr != LSB)
6034 emitcode ("xch", "a,%s",
6035 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6037 aopPut (AOP (result), "a", MSB16 + offr);
6040 if (size >= MSB24 + offr)
6042 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6044 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6047 emitcode ("rlc", "a");
6048 if (sameRegs (AOP (left), AOP (result)) &&
6049 size >= MSB32 + offr && offr != LSB)
6050 emitcode ("xch", "a,%s",
6051 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6053 aopPut (AOP (result), "a", MSB24 + offr);
6056 if (size > MSB32 + offr)
6058 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6060 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6063 emitcode ("rlc", "a");
6064 aopPut (AOP (result), "a", MSB32 + offr);
6067 aopPut (AOP (result), zero, LSB);
6070 /*-----------------------------------------------------------------*/
6071 /* genlshFour - shift four byte by a known amount != 0 */
6072 /*-----------------------------------------------------------------*/
6074 genlshFour (operand * result, operand * left, int shCount)
6078 size = AOP_SIZE (result);
6080 /* if shifting more that 3 bytes */
6085 /* lowest order of left goes to the highest
6086 order of the destination */
6087 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6089 movLeft2Result (left, LSB, result, MSB32, 0);
6090 aopPut (AOP (result), zero, LSB);
6091 aopPut (AOP (result), zero, MSB16);
6092 aopPut (AOP (result), zero, MSB24);
6096 /* more than two bytes */
6097 else if (shCount >= 16)
6099 /* lower order two bytes goes to higher order two bytes */
6101 /* if some more remaining */
6103 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6106 movLeft2Result (left, MSB16, result, MSB32, 0);
6107 movLeft2Result (left, LSB, result, MSB24, 0);
6109 aopPut (AOP (result), zero, MSB16);
6110 aopPut (AOP (result), zero, LSB);
6114 /* if more than 1 byte */
6115 else if (shCount >= 8)
6117 /* lower order three bytes goes to higher order three bytes */
6122 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6124 movLeft2Result (left, LSB, result, MSB16, 0);
6130 movLeft2Result (left, MSB24, result, MSB32, 0);
6131 movLeft2Result (left, MSB16, result, MSB24, 0);
6132 movLeft2Result (left, LSB, result, MSB16, 0);
6133 aopPut (AOP (result), zero, LSB);
6135 else if (shCount == 1)
6136 shiftLLong (left, result, MSB16);
6139 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6140 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6141 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6142 aopPut (AOP (result), zero, LSB);
6147 /* 1 <= shCount <= 7 */
6148 else if (shCount <= 2)
6150 shiftLLong (left, result, LSB);
6152 shiftLLong (result, result, LSB);
6154 /* 3 <= shCount <= 7, optimize */
6157 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6158 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6159 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6163 /*-----------------------------------------------------------------*/
6164 /* genLeftShiftLiteral - left shifting by known count */
6165 /*-----------------------------------------------------------------*/
6167 genLeftShiftLiteral (operand * left,
6172 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6175 freeAsmop (right, NULL, ic, TRUE);
6177 aopOp (left, ic, FALSE);
6178 aopOp (result, ic, FALSE);
6180 size = getSize (operandType (result));
6183 emitcode ("; shift left ", "result %d, left %d", size,
6187 /* I suppose that the left size >= result size */
6192 movLeft2Result (left, size, result, size, 0);
6196 else if (shCount >= (size * 8))
6198 aopPut (AOP (result), zero, size);
6204 genlshOne (result, left, shCount);
6208 genlshTwo (result, left, shCount);
6212 genlshFour (result, left, shCount);
6215 fprintf(stderr, "*** ack! mystery literal shift!\n");
6219 freeAsmop (left, NULL, ic, TRUE);
6220 freeAsmop (result, NULL, ic, TRUE);
6223 /*-----------------------------------------------------------------*/
6224 /* genLeftShift - generates code for left shifting */
6225 /*-----------------------------------------------------------------*/
6227 genLeftShift (iCode * ic)
6229 operand *left, *right, *result;
6232 symbol *tlbl, *tlbl1;
6234 right = IC_RIGHT (ic);
6235 left = IC_LEFT (ic);
6236 result = IC_RESULT (ic);
6238 aopOp (right, ic, FALSE);
6240 /* if the shift count is known then do it
6241 as efficiently as possible */
6242 if (AOP_TYPE (right) == AOP_LIT)
6244 genLeftShiftLiteral (left, right, result, ic);
6248 /* shift count is unknown then we have to form
6249 a loop get the loop count in B : Note: we take
6250 only the lower order byte since shifting
6251 more that 32 bits make no sense anyway, ( the
6252 largest size of an object can be only 32 bits ) */
6254 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6255 emitcode ("inc", "b");
6256 freeAsmop (right, NULL, ic, TRUE);
6257 aopOp (left, ic, FALSE);
6258 aopOp (result, ic, FALSE);
6260 /* now move the left to the result if they are not the
6262 if (!sameRegs (AOP (left), AOP (result)) &&
6263 AOP_SIZE (result) > 1)
6266 size = AOP_SIZE (result);
6270 l = aopGet (AOP (left), offset, FALSE, TRUE);
6271 if (*l == '@' && (IS_AOP_PREG (result)))
6274 emitcode ("mov", "a,%s", l);
6275 aopPut (AOP (result), "a", offset);
6278 aopPut (AOP (result), l, offset);
6283 tlbl = newiTempLabel (NULL);
6284 size = AOP_SIZE (result);
6286 tlbl1 = newiTempLabel (NULL);
6288 /* if it is only one byte then */
6291 symbol *tlbl1 = newiTempLabel (NULL);
6293 l = aopGet (AOP (left), 0, FALSE, FALSE);
6295 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6296 emitcode ("", "%05d$:", tlbl->key + 100);
6297 emitcode ("add", "a,acc");
6298 emitcode ("", "%05d$:", tlbl1->key + 100);
6299 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6300 aopPut (AOP (result), "a", 0);
6304 reAdjustPreg (AOP (result));
6306 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6307 emitcode ("", "%05d$:", tlbl->key + 100);
6308 l = aopGet (AOP (result), offset, FALSE, FALSE);
6310 emitcode ("add", "a,acc");
6311 aopPut (AOP (result), "a", offset++);
6314 l = aopGet (AOP (result), offset, FALSE, FALSE);
6316 emitcode ("rlc", "a");
6317 aopPut (AOP (result), "a", offset++);
6319 reAdjustPreg (AOP (result));
6321 emitcode ("", "%05d$:", tlbl1->key + 100);
6322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6324 freeAsmop (left, NULL, ic, TRUE);
6325 freeAsmop (result, NULL, ic, TRUE);
6328 /*-----------------------------------------------------------------*/
6329 /* genrshOne - right shift a one byte quantity by known count */
6330 /*-----------------------------------------------------------------*/
6332 genrshOne (operand * result, operand * left,
6333 int shCount, int sign)
6335 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6338 /*-----------------------------------------------------------------*/
6339 /* genrshTwo - right shift two bytes by known amount != 0 */
6340 /*-----------------------------------------------------------------*/
6342 genrshTwo (operand * result, operand * left,
6343 int shCount, int sign)
6345 /* if shCount >= 8 */
6350 shiftR1Left2Result (left, MSB16, result, LSB,
6353 movLeft2Result (left, MSB16, result, LSB, sign);
6354 addSign (result, MSB16, sign);
6357 /* 1 <= shCount <= 7 */
6359 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6362 /*-----------------------------------------------------------------*/
6363 /* shiftRLong - shift right one long from left to result */
6364 /* offl = LSB or MSB16 */
6365 /*-----------------------------------------------------------------*/
6367 shiftRLong (operand * left, int offl,
6368 operand * result, int sign)
6370 int isSameRegs=sameRegs(AOP(left),AOP(result));
6372 if (isSameRegs && offl>1) {
6373 // we are in big trouble, but this shouldn't happen
6374 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6377 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6382 emitcode ("rlc", "a");
6383 emitcode ("subb", "a,acc");
6384 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6386 aopPut (AOP(result), zero, MSB32);
6391 emitcode ("clr", "c");
6393 emitcode ("mov", "c,acc.7");
6396 emitcode ("rrc", "a");
6398 if (isSameRegs && offl==MSB16) {
6399 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6401 aopPut (AOP (result), "a", MSB32);
6402 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6405 emitcode ("rrc", "a");
6406 if (isSameRegs && offl==1) {
6407 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6409 aopPut (AOP (result), "a", MSB24);
6410 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6412 emitcode ("rrc", "a");
6413 aopPut (AOP (result), "a", MSB16 - offl);
6417 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6418 emitcode ("rrc", "a");
6419 aopPut (AOP (result), "a", LSB);
6423 /*-----------------------------------------------------------------*/
6424 /* genrshFour - shift four byte by a known amount != 0 */
6425 /*-----------------------------------------------------------------*/
6427 genrshFour (operand * result, operand * left,
6428 int shCount, int sign)
6430 /* if shifting more that 3 bytes */
6435 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6437 movLeft2Result (left, MSB32, result, LSB, sign);
6438 addSign (result, MSB16, sign);
6440 else if (shCount >= 16)
6444 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6447 movLeft2Result (left, MSB24, result, LSB, 0);
6448 movLeft2Result (left, MSB32, result, MSB16, sign);
6450 addSign (result, MSB24, sign);
6452 else if (shCount >= 8)
6456 shiftRLong (left, MSB16, result, sign);
6457 else if (shCount == 0)
6459 movLeft2Result (left, MSB16, result, LSB, 0);
6460 movLeft2Result (left, MSB24, result, MSB16, 0);
6461 movLeft2Result (left, MSB32, result, MSB24, sign);
6462 addSign (result, MSB32, sign);
6466 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6467 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6468 /* the last shift is signed */
6469 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6470 addSign (result, MSB32, sign);
6474 { /* 1 <= shCount <= 7 */
6477 shiftRLong (left, LSB, result, sign);
6479 shiftRLong (result, LSB, result, sign);
6483 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6484 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6485 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6490 /*-----------------------------------------------------------------*/
6491 /* genRightShiftLiteral - right shifting by known count */
6492 /*-----------------------------------------------------------------*/
6494 genRightShiftLiteral (operand * left,
6500 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6503 freeAsmop (right, NULL, ic, TRUE);
6505 aopOp (left, ic, FALSE);
6506 aopOp (result, ic, FALSE);
6509 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6513 size = getDataSize (left);
6514 /* test the LEFT size !!! */
6516 /* I suppose that the left size >= result size */
6519 size = getDataSize (result);
6521 movLeft2Result (left, size, result, size, 0);
6524 else if (shCount >= (size * 8))
6527 /* get sign in acc.7 */
6528 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6529 addSign (result, LSB, sign);
6536 genrshOne (result, left, shCount, sign);
6540 genrshTwo (result, left, shCount, sign);
6544 genrshFour (result, left, shCount, sign);
6550 freeAsmop (left, NULL, ic, TRUE);
6551 freeAsmop (result, NULL, ic, TRUE);
6555 /*-----------------------------------------------------------------*/
6556 /* genSignedRightShift - right shift of signed number */
6557 /*-----------------------------------------------------------------*/
6559 genSignedRightShift (iCode * ic)
6561 operand *right, *left, *result;
6564 symbol *tlbl, *tlbl1;
6566 /* we do it the hard way put the shift count in b
6567 and loop thru preserving the sign */
6569 right = IC_RIGHT (ic);
6570 left = IC_LEFT (ic);
6571 result = IC_RESULT (ic);
6573 aopOp (right, ic, FALSE);
6576 if (AOP_TYPE (right) == AOP_LIT)
6578 genRightShiftLiteral (left, right, result, ic, 1);
6581 /* shift count is unknown then we have to form
6582 a loop get the loop count in B : Note: we take
6583 only the lower order byte since shifting
6584 more that 32 bits make no sense anyway, ( the
6585 largest size of an object can be only 32 bits ) */
6587 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6588 emitcode ("inc", "b");
6589 freeAsmop (right, NULL, ic, TRUE);
6590 aopOp (left, ic, FALSE);
6591 aopOp (result, ic, FALSE);
6593 /* now move the left to the result if they are not the
6595 if (!sameRegs (AOP (left), AOP (result)) &&
6596 AOP_SIZE (result) > 1)
6599 size = AOP_SIZE (result);
6603 l = aopGet (AOP (left), offset, FALSE, TRUE);
6604 if (*l == '@' && IS_AOP_PREG (result))
6607 emitcode ("mov", "a,%s", l);
6608 aopPut (AOP (result), "a", offset);
6611 aopPut (AOP (result), l, offset);
6616 /* mov the highest order bit to OVR */
6617 tlbl = newiTempLabel (NULL);
6618 tlbl1 = newiTempLabel (NULL);
6620 size = AOP_SIZE (result);
6622 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6623 emitcode ("rlc", "a");
6624 emitcode ("mov", "ov,c");
6625 /* if it is only one byte then */
6628 l = aopGet (AOP (left), 0, FALSE, FALSE);
6630 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6631 emitcode ("", "%05d$:", tlbl->key + 100);
6632 emitcode ("mov", "c,ov");
6633 emitcode ("rrc", "a");
6634 emitcode ("", "%05d$:", tlbl1->key + 100);
6635 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6636 aopPut (AOP (result), "a", 0);
6640 reAdjustPreg (AOP (result));
6641 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6642 emitcode ("", "%05d$:", tlbl->key + 100);
6643 emitcode ("mov", "c,ov");
6646 l = aopGet (AOP (result), offset, FALSE, FALSE);
6648 emitcode ("rrc", "a");
6649 aopPut (AOP (result), "a", offset--);
6651 reAdjustPreg (AOP (result));
6652 emitcode ("", "%05d$:", tlbl1->key + 100);
6653 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6656 freeAsmop (left, NULL, ic, TRUE);
6657 freeAsmop (result, NULL, ic, TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* genRightShift - generate code for right shifting */
6662 /*-----------------------------------------------------------------*/
6664 genRightShift (iCode * ic)
6666 operand *right, *left, *result;
6670 symbol *tlbl, *tlbl1;
6672 /* if signed then we do it the hard way preserve the
6673 sign bit moving it inwards */
6674 retype = getSpec (operandType (IC_RESULT (ic)));
6676 if (!SPEC_USIGN (retype))
6678 genSignedRightShift (ic);
6682 /* signed & unsigned types are treated the same : i.e. the
6683 signed is NOT propagated inwards : quoting from the
6684 ANSI - standard : "for E1 >> E2, is equivalent to division
6685 by 2**E2 if unsigned or if it has a non-negative value,
6686 otherwise the result is implementation defined ", MY definition
6687 is that the sign does not get propagated */
6689 right = IC_RIGHT (ic);
6690 left = IC_LEFT (ic);
6691 result = IC_RESULT (ic);
6693 aopOp (right, ic, FALSE);
6695 /* if the shift count is known then do it
6696 as efficiently as possible */
6697 if (AOP_TYPE (right) == AOP_LIT)
6699 genRightShiftLiteral (left, right, result, ic, 0);
6703 /* shift count is unknown then we have to form
6704 a loop get the loop count in B : Note: we take
6705 only the lower order byte since shifting
6706 more that 32 bits make no sense anyway, ( the
6707 largest size of an object can be only 32 bits ) */
6709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6710 emitcode ("inc", "b");
6711 freeAsmop (right, NULL, ic, TRUE);
6712 aopOp (left, ic, FALSE);
6713 aopOp (result, ic, FALSE);
6715 /* now move the left to the result if they are not the
6717 if (!sameRegs (AOP (left), AOP (result)) &&
6718 AOP_SIZE (result) > 1)
6721 size = AOP_SIZE (result);
6725 l = aopGet (AOP (left), offset, FALSE, TRUE);
6726 if (*l == '@' && IS_AOP_PREG (result))
6729 emitcode ("mov", "a,%s", l);
6730 aopPut (AOP (result), "a", offset);
6733 aopPut (AOP (result), l, offset);
6738 tlbl = newiTempLabel (NULL);
6739 tlbl1 = newiTempLabel (NULL);
6740 size = AOP_SIZE (result);
6743 /* if it is only one byte then */
6746 l = aopGet (AOP (left), 0, FALSE, FALSE);
6748 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6749 emitcode ("", "%05d$:", tlbl->key + 100);
6751 emitcode ("rrc", "a");
6752 emitcode ("", "%05d$:", tlbl1->key + 100);
6753 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6754 aopPut (AOP (result), "a", 0);
6758 reAdjustPreg (AOP (result));
6759 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6760 emitcode ("", "%05d$:", tlbl->key + 100);
6764 l = aopGet (AOP (result), offset, FALSE, FALSE);
6766 emitcode ("rrc", "a");
6767 aopPut (AOP (result), "a", offset--);
6769 reAdjustPreg (AOP (result));
6771 emitcode ("", "%05d$:", tlbl1->key + 100);
6772 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6775 freeAsmop (left, NULL, ic, TRUE);
6776 freeAsmop (result, NULL, ic, TRUE);
6779 /*-----------------------------------------------------------------*/
6780 /* genUnpackBits - generates code for unpacking bits */
6781 /*-----------------------------------------------------------------*/
6783 genUnpackBits (operand * result, char *rname, int ptype)
6791 etype = getSpec (operandType (result));
6792 rsize = getSize (operandType (result));
6793 /* read the first byte */
6799 emitcode ("mov", "a,@%s", rname);
6803 emitcode ("movx", "a,@%s", rname);
6807 emitcode ("movx", "a,@dptr");
6811 emitcode ("clr", "a");
6812 emitcode ("movc", "a,@a+dptr");
6816 emitcode ("lcall", "__gptrget");
6820 rlen = SPEC_BLEN (etype);
6822 /* if we have bitdisplacement then it fits */
6823 /* into this byte completely or if length is */
6824 /* less than a byte */
6825 if ((shCnt = SPEC_BSTR (etype)) ||
6826 (SPEC_BLEN (etype) <= 8))
6829 /* shift right acc */
6832 emitcode ("anl", "a,#0x%02x",
6833 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6834 aopPut (AOP (result), "a", offset++);
6838 /* bit field did not fit in a byte */
6839 aopPut (AOP (result), "a", offset++);
6848 emitcode ("inc", "%s", rname);
6849 emitcode ("mov", "a,@%s", rname);
6853 emitcode ("inc", "%s", rname);
6854 emitcode ("movx", "a,@%s", rname);
6858 emitcode ("inc", "dptr");
6859 emitcode ("movx", "a,@dptr");
6863 emitcode ("clr", "a");
6864 emitcode ("inc", "dptr");
6865 emitcode ("movc", "a,@a+dptr");
6869 emitcode ("inc", "dptr");
6870 emitcode ("lcall", "__gptrget");
6875 /* if we are done */
6879 aopPut (AOP (result), "a", offset++);
6885 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6887 aopPut (AOP (result), "a", offset++);
6895 aopPut (AOP (result), zero, offset++);
6901 /*-----------------------------------------------------------------*/
6902 /* genDataPointerGet - generates code when ptr offset is known */
6903 /*-----------------------------------------------------------------*/
6905 genDataPointerGet (operand * left,
6911 int size, offset = 0;
6912 aopOp (result, ic, TRUE);
6914 /* get the string representation of the name */
6915 l = aopGet (AOP (left), 0, FALSE, TRUE);
6916 size = AOP_SIZE (result);
6920 sprintf (buffer, "(%s + %d)", l + 1, offset);
6922 sprintf (buffer, "%s", l + 1);
6923 aopPut (AOP (result), buffer, offset++);
6926 freeAsmop (left, NULL, ic, TRUE);
6927 freeAsmop (result, NULL, ic, TRUE);
6930 /*-----------------------------------------------------------------*/
6931 /* genNearPointerGet - emitcode for near pointer fetch */
6932 /*-----------------------------------------------------------------*/
6934 genNearPointerGet (operand * left,
6942 sym_link *rtype, *retype;
6943 sym_link *ltype = operandType (left);
6946 rtype = operandType (result);
6947 retype = getSpec (rtype);
6949 aopOp (left, ic, FALSE);
6951 /* if left is rematerialisable and
6952 result is not bit variable type and
6953 the left is pointer to data space i.e
6954 lower 128 bytes of space */
6955 if (AOP_TYPE (left) == AOP_IMMD &&
6956 !IS_BITVAR (retype) &&
6957 DCL_TYPE (ltype) == POINTER)
6959 genDataPointerGet (left, result, ic);
6963 /* if the value is already in a pointer register
6964 then don't need anything more */
6965 if (!AOP_INPREG (AOP (left)))
6967 /* otherwise get a free pointer register */
6969 preg = getFreePtr (ic, &aop, FALSE);
6970 emitcode ("mov", "%s,%s",
6972 aopGet (AOP (left), 0, FALSE, TRUE));
6976 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6978 //aopOp (result, ic, FALSE);
6979 aopOp (result, ic, result?TRUE:FALSE);
6981 /* if bitfield then unpack the bits */
6982 if (IS_BITVAR (retype))
6983 genUnpackBits (result, rname, POINTER);
6986 /* we have can just get the values */
6987 int size = AOP_SIZE (result);
6992 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6995 emitcode ("mov", "a,@%s", rname);
6996 aopPut (AOP (result), "a", offset);
7000 sprintf (buffer, "@%s", rname);
7001 aopPut (AOP (result), buffer, offset);
7005 emitcode ("inc", "%s", rname);
7009 /* now some housekeeping stuff */
7010 if (aop) /* we had to allocate for this iCode */
7012 if (pi) { /* post increment present */
7013 aopPut(AOP ( left ),rname,0);
7015 freeAsmop (NULL, aop, ic, TRUE);
7019 /* we did not allocate which means left
7020 already in a pointer register, then
7021 if size > 0 && this could be used again
7022 we have to point it back to where it
7024 if ((AOP_SIZE (result) > 1 &&
7025 !OP_SYMBOL (left)->remat &&
7026 (OP_SYMBOL (left)->liveTo > ic->seq ||
7030 int size = AOP_SIZE (result) - 1;
7032 emitcode ("dec", "%s", rname);
7037 freeAsmop (left, NULL, ic, TRUE);
7038 freeAsmop (result, NULL, ic, TRUE);
7039 if (pi) pi->generated = 1;
7042 /*-----------------------------------------------------------------*/
7043 /* genPagedPointerGet - emitcode for paged pointer fetch */
7044 /*-----------------------------------------------------------------*/
7046 genPagedPointerGet (operand * left,
7054 sym_link *rtype, *retype;
7056 rtype = operandType (result);
7057 retype = getSpec (rtype);
7059 aopOp (left, ic, FALSE);
7061 /* if the value is already in a pointer register
7062 then don't need anything more */
7063 if (!AOP_INPREG (AOP (left)))
7065 /* otherwise get a free pointer register */
7067 preg = getFreePtr (ic, &aop, FALSE);
7068 emitcode ("mov", "%s,%s",
7070 aopGet (AOP (left), 0, FALSE, TRUE));
7074 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7076 aopOp (result, ic, FALSE);
7078 /* if bitfield then unpack the bits */
7079 if (IS_BITVAR (retype))
7080 genUnpackBits (result, rname, PPOINTER);
7083 /* we have can just get the values */
7084 int size = AOP_SIZE (result);
7090 emitcode ("movx", "a,@%s", rname);
7091 aopPut (AOP (result), "a", offset);
7096 emitcode ("inc", "%s", rname);
7100 /* now some housekeeping stuff */
7101 if (aop) /* we had to allocate for this iCode */
7103 if (pi) aopPut ( AOP (left), rname, 0);
7104 freeAsmop (NULL, aop, ic, TRUE);
7108 /* we did not allocate which means left
7109 already in a pointer register, then
7110 if size > 0 && this could be used again
7111 we have to point it back to where it
7113 if ((AOP_SIZE (result) > 1 &&
7114 !OP_SYMBOL (left)->remat &&
7115 (OP_SYMBOL (left)->liveTo > ic->seq ||
7119 int size = AOP_SIZE (result) - 1;
7121 emitcode ("dec", "%s", rname);
7126 freeAsmop (left, NULL, ic, TRUE);
7127 freeAsmop (result, NULL, ic, TRUE);
7128 if (pi) pi->generated = 1;
7132 /*-----------------------------------------------------------------*/
7133 /* genFarPointerGet - gget value from far space */
7134 /*-----------------------------------------------------------------*/
7136 genFarPointerGet (operand * left,
7137 operand * result, iCode * ic, iCode * pi)
7140 sym_link *retype = getSpec (operandType (result));
7142 aopOp (left, ic, FALSE);
7144 /* if the operand is already in dptr
7145 then we do nothing else we move the value to dptr */
7146 if (AOP_TYPE (left) != AOP_STR)
7148 /* if this is remateriazable */
7149 if (AOP_TYPE (left) == AOP_IMMD)
7150 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7152 { /* we need to get it byte by byte */
7153 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7154 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7157 /* so dptr know contains the address */
7158 aopOp (result, ic, FALSE);
7160 /* if bit then unpack */
7161 if (IS_BITVAR (retype))
7162 genUnpackBits (result, "dptr", FPOINTER);
7165 size = AOP_SIZE (result);
7170 emitcode ("movx", "a,@dptr");
7171 aopPut (AOP (result), "a", offset++);
7173 emitcode ("inc", "dptr");
7177 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7178 aopPut ( AOP (left), "dpl", 0);
7179 aopPut ( AOP (left), "dph", 1);
7182 freeAsmop (left, NULL, ic, TRUE);
7183 freeAsmop (result, NULL, ic, TRUE);
7186 /*-----------------------------------------------------------------*/
7187 /* genCodePointerGet - gget value from code space */
7188 /*-----------------------------------------------------------------*/
7190 genCodePointerGet (operand * left,
7191 operand * result, iCode * ic, iCode *pi)
7194 sym_link *retype = getSpec (operandType (result));
7196 aopOp (left, ic, FALSE);
7198 /* if the operand is already in dptr
7199 then we do nothing else we move the value to dptr */
7200 if (AOP_TYPE (left) != AOP_STR)
7202 /* if this is remateriazable */
7203 if (AOP_TYPE (left) == AOP_IMMD)
7204 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7206 { /* we need to get it byte by byte */
7207 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7208 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7211 /* so dptr know contains the address */
7212 aopOp (result, ic, FALSE);
7214 /* if bit then unpack */
7215 if (IS_BITVAR (retype))
7216 genUnpackBits (result, "dptr", CPOINTER);
7219 size = AOP_SIZE (result);
7224 emitcode ("clr", "a");
7225 emitcode ("movc", "a,@a+dptr");
7226 aopPut (AOP (result), "a", offset++);
7228 emitcode ("inc", "dptr");
7232 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7233 aopPut ( AOP (left), "dpl", 0);
7234 aopPut ( AOP (left), "dph", 1);
7237 freeAsmop (left, NULL, ic, TRUE);
7238 freeAsmop (result, NULL, ic, TRUE);
7241 /*-----------------------------------------------------------------*/
7242 /* genGenPointerGet - gget value from generic pointer space */
7243 /*-----------------------------------------------------------------*/
7245 genGenPointerGet (operand * left,
7246 operand * result, iCode * ic, iCode *pi)
7249 sym_link *retype = getSpec (operandType (result));
7251 aopOp (left, ic, FALSE);
7253 /* if the operand is already in dptr
7254 then we do nothing else we move the value to dptr */
7255 if (AOP_TYPE (left) != AOP_STR)
7257 /* if this is remateriazable */
7258 if (AOP_TYPE (left) == AOP_IMMD)
7260 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7261 emitcode ("mov", "b,#%d", pointerCode (retype));
7264 { /* we need to get it byte by byte */
7265 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7266 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7267 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7270 /* so dptr know contains the address */
7271 aopOp (result, ic, FALSE);
7273 /* if bit then unpack */
7274 if (IS_BITVAR (retype))
7275 genUnpackBits (result, "dptr", GPOINTER);
7278 size = AOP_SIZE (result);
7283 emitcode ("lcall", "__gptrget");
7284 aopPut (AOP (result), "a", offset++);
7286 emitcode ("inc", "dptr");
7290 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7291 aopPut ( AOP (left), "dpl", 0);
7292 aopPut ( AOP (left), "dph", 1);
7295 freeAsmop (left, NULL, ic, TRUE);
7296 freeAsmop (result, NULL, ic, TRUE);
7299 /*-----------------------------------------------------------------*/
7300 /* genPointerGet - generate code for pointer get */
7301 /*-----------------------------------------------------------------*/
7303 genPointerGet (iCode * ic, iCode *pi)
7305 operand *left, *result;
7306 sym_link *type, *etype;
7309 left = IC_LEFT (ic);
7310 result = IC_RESULT (ic);
7312 /* depending on the type of pointer we need to
7313 move it to the correct pointer register */
7314 type = operandType (left);
7315 etype = getSpec (type);
7316 /* if left is of type of pointer then it is simple */
7317 if (IS_PTR (type) && !IS_FUNC (type->next))
7318 p_type = DCL_TYPE (type);
7321 /* we have to go by the storage class */
7322 p_type = PTR_TYPE (SPEC_OCLS (etype));
7325 /* now that we have the pointer type we assign
7326 the pointer values */
7332 genNearPointerGet (left, result, ic, pi);
7336 genPagedPointerGet (left, result, ic, pi);
7340 genFarPointerGet (left, result, ic, pi);
7344 genCodePointerGet (left, result, ic, pi);
7348 genGenPointerGet (left, result, ic, pi);
7354 /*-----------------------------------------------------------------*/
7355 /* genPackBits - generates code for packed bit storage */
7356 /*-----------------------------------------------------------------*/
7358 genPackBits (sym_link * etype,
7360 char *rname, int p_type)
7368 blen = SPEC_BLEN (etype);
7369 bstr = SPEC_BSTR (etype);
7371 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7374 /* if the bit lenth is less than or */
7375 /* it exactly fits a byte then */
7376 if (SPEC_BLEN (etype) <= 8)
7378 shCount = SPEC_BSTR (etype);
7380 /* shift left acc */
7383 if (SPEC_BLEN (etype) < 8)
7384 { /* if smaller than a byte */
7390 emitcode ("mov", "b,a");
7391 emitcode ("mov", "a,@%s", rname);
7395 emitcode ("mov", "b,a");
7396 emitcode ("movx", "a,@dptr");
7400 emitcode ("push", "b");
7401 emitcode ("push", "acc");
7402 emitcode ("lcall", "__gptrget");
7403 emitcode ("pop", "b");
7407 emitcode ("anl", "a,#0x%02x", (unsigned char)
7408 ((unsigned char) (0xFF << (blen + bstr)) |
7409 (unsigned char) (0xFF >> (8 - bstr))));
7410 emitcode ("orl", "a,b");
7411 if (p_type == GPOINTER)
7412 emitcode ("pop", "b");
7419 emitcode ("mov", "@%s,a", rname);
7423 emitcode ("movx", "@dptr,a");
7427 emitcode ("lcall", "__gptrput");
7432 if (SPEC_BLEN (etype) <= 8)
7435 emitcode ("inc", "%s", rname);
7436 rLen = SPEC_BLEN (etype);
7438 /* now generate for lengths greater than one byte */
7442 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7454 emitcode ("mov", "@%s,a", rname);
7457 emitcode ("mov", "@%s,%s", rname, l);
7462 emitcode ("movx", "@dptr,a");
7467 emitcode ("lcall", "__gptrput");
7470 emitcode ("inc", "%s", rname);
7475 /* last last was not complete */
7478 /* save the byte & read byte */
7482 emitcode ("mov", "b,a");
7483 emitcode ("mov", "a,@%s", rname);
7487 emitcode ("mov", "b,a");
7488 emitcode ("movx", "a,@dptr");
7492 emitcode ("push", "b");
7493 emitcode ("push", "acc");
7494 emitcode ("lcall", "__gptrget");
7495 emitcode ("pop", "b");
7499 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7500 emitcode ("orl", "a,b");
7503 if (p_type == GPOINTER)
7504 emitcode ("pop", "b");
7510 emitcode ("mov", "@%s,a", rname);
7514 emitcode ("movx", "@dptr,a");
7518 emitcode ("lcall", "__gptrput");
7522 /*-----------------------------------------------------------------*/
7523 /* genDataPointerSet - remat pointer to data space */
7524 /*-----------------------------------------------------------------*/
7526 genDataPointerSet (operand * right,
7530 int size, offset = 0;
7531 char *l, buffer[256];
7533 aopOp (right, ic, FALSE);
7535 l = aopGet (AOP (result), 0, FALSE, TRUE);
7536 size = AOP_SIZE (right);
7540 sprintf (buffer, "(%s + %d)", l + 1, offset);
7542 sprintf (buffer, "%s", l + 1);
7543 emitcode ("mov", "%s,%s", buffer,
7544 aopGet (AOP (right), offset++, FALSE, FALSE));
7547 freeAsmop (right, NULL, ic, TRUE);
7548 freeAsmop (result, NULL, ic, TRUE);
7551 /*-----------------------------------------------------------------*/
7552 /* genNearPointerSet - emitcode for near pointer put */
7553 /*-----------------------------------------------------------------*/
7555 genNearPointerSet (operand * right,
7563 sym_link *retype, *letype;
7564 sym_link *ptype = operandType (result);
7566 retype = getSpec (operandType (right));
7567 letype = getSpec (ptype);
7568 aopOp (result, ic, FALSE);
7570 /* if the result is rematerializable &
7571 in data space & not a bit variable */
7572 if (AOP_TYPE (result) == AOP_IMMD &&
7573 DCL_TYPE (ptype) == POINTER &&
7574 !IS_BITVAR (retype) &&
7575 !IS_BITVAR (letype))
7577 genDataPointerSet (right, result, ic);
7581 /* if the value is already in a pointer register
7582 then don't need anything more */
7583 if (!AOP_INPREG (AOP (result)))
7585 /* otherwise get a free pointer register */
7587 preg = getFreePtr (ic, &aop, FALSE);
7588 emitcode ("mov", "%s,%s",
7590 aopGet (AOP (result), 0, FALSE, TRUE));
7594 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7596 aopOp (right, ic, FALSE);
7598 /* if bitfield then unpack the bits */
7599 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7600 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7603 /* we have can just get the values */
7604 int size = AOP_SIZE (right);
7609 l = aopGet (AOP (right), offset, FALSE, TRUE);
7613 emitcode ("mov", "@%s,a", rname);
7616 emitcode ("mov", "@%s,%s", rname, l);
7618 emitcode ("inc", "%s", rname);
7623 /* now some housekeeping stuff */
7624 if (aop) /* we had to allocate for this iCode */
7626 if (pi) aopPut (AOP (result),rname,0);
7627 freeAsmop (NULL, aop, ic, TRUE);
7631 /* we did not allocate which means left
7632 already in a pointer register, then
7633 if size > 0 && this could be used again
7634 we have to point it back to where it
7636 if ((AOP_SIZE (right) > 1 &&
7637 !OP_SYMBOL (result)->remat &&
7638 (OP_SYMBOL (result)->liveTo > ic->seq ||
7642 int size = AOP_SIZE (right) - 1;
7644 emitcode ("dec", "%s", rname);
7649 if (pi) pi->generated = 1;
7650 freeAsmop (result, NULL, ic, TRUE);
7651 freeAsmop (right, NULL, ic, TRUE);
7654 /*-----------------------------------------------------------------*/
7655 /* genPagedPointerSet - emitcode for Paged pointer put */
7656 /*-----------------------------------------------------------------*/
7658 genPagedPointerSet (operand * right,
7666 sym_link *retype, *letype;
7668 retype = getSpec (operandType (right));
7669 letype = getSpec (operandType (result));
7671 aopOp (result, ic, FALSE);
7673 /* if the value is already in a pointer register
7674 then don't need anything more */
7675 if (!AOP_INPREG (AOP (result)))
7677 /* otherwise get a free pointer register */
7679 preg = getFreePtr (ic, &aop, FALSE);
7680 emitcode ("mov", "%s,%s",
7682 aopGet (AOP (result), 0, FALSE, TRUE));
7686 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7688 aopOp (right, ic, FALSE);
7690 /* if bitfield then unpack the bits */
7691 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7692 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7695 /* we have can just get the values */
7696 int size = AOP_SIZE (right);
7701 l = aopGet (AOP (right), offset, FALSE, TRUE);
7704 emitcode ("movx", "@%s,a", rname);
7707 emitcode ("inc", "%s", rname);
7713 /* now some housekeeping stuff */
7714 if (aop) /* we had to allocate for this iCode */
7716 if (pi) aopPut (AOP (result),rname,0);
7717 freeAsmop (NULL, aop, ic, TRUE);
7721 /* we did not allocate which means left
7722 already in a pointer register, then
7723 if size > 0 && this could be used again
7724 we have to point it back to where it
7726 if (AOP_SIZE (right) > 1 &&
7727 !OP_SYMBOL (result)->remat &&
7728 (OP_SYMBOL (result)->liveTo > ic->seq ||
7731 int size = AOP_SIZE (right) - 1;
7733 emitcode ("dec", "%s", rname);
7738 if (pi) pi->generated = 1;
7739 freeAsmop (result, NULL, ic, TRUE);
7740 freeAsmop (right, NULL, ic, TRUE);
7745 /*-----------------------------------------------------------------*/
7746 /* genFarPointerSet - set value from far space */
7747 /*-----------------------------------------------------------------*/
7749 genFarPointerSet (operand * right,
7750 operand * result, iCode * ic, iCode * pi)
7753 sym_link *retype = getSpec (operandType (right));
7754 sym_link *letype = getSpec (operandType (result));
7755 aopOp (result, ic, FALSE);
7757 /* if the operand is already in dptr
7758 then we do nothing else we move the value to dptr */
7759 if (AOP_TYPE (result) != AOP_STR)
7761 /* if this is remateriazable */
7762 if (AOP_TYPE (result) == AOP_IMMD)
7763 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7765 { /* we need to get it byte by byte */
7766 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7767 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7770 /* so dptr know contains the address */
7771 aopOp (right, ic, FALSE);
7773 /* if bit then unpack */
7774 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7775 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7778 size = AOP_SIZE (right);
7783 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7785 emitcode ("movx", "@dptr,a");
7787 emitcode ("inc", "dptr");
7790 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7791 aopPut (AOP(result),"dpl",0);
7792 aopPut (AOP(result),"dph",1);
7795 freeAsmop (result, NULL, ic, TRUE);
7796 freeAsmop (right, NULL, ic, TRUE);
7799 /*-----------------------------------------------------------------*/
7800 /* genGenPointerSet - set value from generic pointer space */
7801 /*-----------------------------------------------------------------*/
7803 genGenPointerSet (operand * right,
7804 operand * result, iCode * ic, iCode * pi)
7807 sym_link *retype = getSpec (operandType (right));
7808 sym_link *letype = getSpec (operandType (result));
7810 aopOp (result, ic, FALSE);
7812 /* if the operand is already in dptr
7813 then we do nothing else we move the value to dptr */
7814 if (AOP_TYPE (result) != AOP_STR)
7816 /* if this is remateriazable */
7817 if (AOP_TYPE (result) == AOP_IMMD)
7819 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7820 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7823 { /* we need to get it byte by byte */
7824 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7825 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7826 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7829 /* so dptr know contains the address */
7830 aopOp (right, ic, FALSE);
7832 /* if bit then unpack */
7833 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7834 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7837 size = AOP_SIZE (right);
7842 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7844 emitcode ("lcall", "__gptrput");
7846 emitcode ("inc", "dptr");
7850 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7851 aopPut (AOP(result),"dpl",0);
7852 aopPut (AOP(result),"dph",1);
7855 freeAsmop (result, NULL, ic, TRUE);
7856 freeAsmop (right, NULL, ic, TRUE);
7859 /*-----------------------------------------------------------------*/
7860 /* genPointerSet - stores the value into a pointer location */
7861 /*-----------------------------------------------------------------*/
7863 genPointerSet (iCode * ic, iCode *pi)
7865 operand *right, *result;
7866 sym_link *type, *etype;
7869 right = IC_RIGHT (ic);
7870 result = IC_RESULT (ic);
7872 /* depending on the type of pointer we need to
7873 move it to the correct pointer register */
7874 type = operandType (result);
7875 etype = getSpec (type);
7876 /* if left is of type of pointer then it is simple */
7877 if (IS_PTR (type) && !IS_FUNC (type->next))
7879 p_type = DCL_TYPE (type);
7883 /* we have to go by the storage class */
7884 p_type = PTR_TYPE (SPEC_OCLS (etype));
7887 /* now that we have the pointer type we assign
7888 the pointer values */
7894 genNearPointerSet (right, result, ic, pi);
7898 genPagedPointerSet (right, result, ic, pi);
7902 genFarPointerSet (right, result, ic, pi);
7906 genGenPointerSet (right, result, ic, pi);
7912 /*-----------------------------------------------------------------*/
7913 /* genIfx - generate code for Ifx statement */
7914 /*-----------------------------------------------------------------*/
7916 genIfx (iCode * ic, iCode * popIc)
7918 operand *cond = IC_COND (ic);
7921 aopOp (cond, ic, FALSE);
7923 /* get the value into acc */
7924 if (AOP_TYPE (cond) != AOP_CRY)
7928 /* the result is now in the accumulator */
7929 freeAsmop (cond, NULL, ic, TRUE);
7931 /* if there was something to be popped then do it */
7935 /* if the condition is a bit variable */
7936 if (isbit && IS_ITEMP (cond) &&
7938 genIfxJump (ic, SPIL_LOC (cond)->rname);
7939 else if (isbit && !IS_ITEMP (cond))
7940 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7942 genIfxJump (ic, "a");
7947 /*-----------------------------------------------------------------*/
7948 /* genAddrOf - generates code for address of */
7949 /*-----------------------------------------------------------------*/
7951 genAddrOf (iCode * ic)
7953 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7956 aopOp (IC_RESULT (ic), ic, FALSE);
7958 /* if the operand is on the stack then we
7959 need to get the stack offset of this
7963 /* if it has an offset then we need to compute
7967 emitcode ("mov", "a,_bp");
7968 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7969 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7973 /* we can just move _bp */
7974 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7976 /* fill the result with zero */
7977 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7982 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7988 /* object not on stack then we need the name */
7989 size = AOP_SIZE (IC_RESULT (ic));
7994 char s[SDCC_NAME_MAX];
7996 sprintf (s, "#(%s >> %d)",
8000 sprintf (s, "#%s", sym->rname);
8001 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8005 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8009 /*-----------------------------------------------------------------*/
8010 /* genFarFarAssign - assignment when both are in far space */
8011 /*-----------------------------------------------------------------*/
8013 genFarFarAssign (operand * result, operand * right, iCode * ic)
8015 int size = AOP_SIZE (right);
8018 /* first push the right side on to the stack */
8021 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8023 emitcode ("push", "acc");
8026 freeAsmop (right, NULL, ic, FALSE);
8027 /* now assign DPTR to result */
8028 aopOp (result, ic, FALSE);
8029 size = AOP_SIZE (result);
8032 emitcode ("pop", "acc");
8033 aopPut (AOP (result), "a", --offset);
8035 freeAsmop (result, NULL, ic, FALSE);
8039 /*-----------------------------------------------------------------*/
8040 /* genAssign - generate code for assignment */
8041 /*-----------------------------------------------------------------*/
8043 genAssign (iCode * ic)
8045 operand *result, *right;
8047 unsigned long lit = 0L;
8049 D(emitcode(";","genAssign"));
8051 result = IC_RESULT (ic);
8052 right = IC_RIGHT (ic);
8054 /* if they are the same */
8055 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8058 aopOp (right, ic, FALSE);
8060 /* special case both in far space */
8061 if (AOP_TYPE (right) == AOP_DPTR &&
8062 IS_TRUE_SYMOP (result) &&
8063 isOperandInFarSpace (result))
8066 genFarFarAssign (result, right, ic);
8070 aopOp (result, ic, TRUE);
8072 /* if they are the same registers */
8073 if (sameRegs (AOP (right), AOP (result)))
8076 /* if the result is a bit */
8077 if (AOP_TYPE (result) == AOP_CRY)
8080 /* if the right size is a literal then
8081 we know what the value is */
8082 if (AOP_TYPE (right) == AOP_LIT)
8084 if (((int) operandLitValue (right)))
8085 aopPut (AOP (result), one, 0);
8087 aopPut (AOP (result), zero, 0);
8091 /* the right is also a bit variable */
8092 if (AOP_TYPE (right) == AOP_CRY)
8094 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8095 aopPut (AOP (result), "c", 0);
8101 aopPut (AOP (result), "a", 0);
8105 /* bit variables done */
8107 size = AOP_SIZE (result);
8109 if (AOP_TYPE (right) == AOP_LIT)
8110 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8112 (AOP_TYPE (result) != AOP_REG) &&
8113 (AOP_TYPE (right) == AOP_LIT) &&
8114 !IS_FLOAT (operandType (right)) &&
8117 emitcode ("clr", "a");
8120 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8121 aopPut (AOP (result), "a", size);
8123 aopPut (AOP (result),
8124 aopGet (AOP (right), size, FALSE, FALSE),
8132 aopPut (AOP (result),
8133 aopGet (AOP (right), offset, FALSE, FALSE),
8140 freeAsmop (right, NULL, ic, TRUE);
8141 freeAsmop (result, NULL, ic, TRUE);
8144 /*-----------------------------------------------------------------*/
8145 /* genJumpTab - genrates code for jump table */
8146 /*-----------------------------------------------------------------*/
8148 genJumpTab (iCode * ic)
8153 aopOp (IC_JTCOND (ic), ic, FALSE);
8154 /* get the condition into accumulator */
8155 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8157 /* multiply by three */
8158 emitcode ("add", "a,acc");
8159 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8160 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8162 jtab = newiTempLabel (NULL);
8163 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8164 emitcode ("jmp", "@a+dptr");
8165 emitcode ("", "%05d$:", jtab->key + 100);
8166 /* now generate the jump labels */
8167 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8168 jtab = setNextItem (IC_JTLABELS (ic)))
8169 emitcode ("ljmp", "%05d$", jtab->key + 100);
8173 /*-----------------------------------------------------------------*/
8174 /* genCast - gen code for casting */
8175 /*-----------------------------------------------------------------*/
8177 genCast (iCode * ic)
8179 operand *result = IC_RESULT (ic);
8180 sym_link *ctype = operandType (IC_LEFT (ic));
8181 sym_link *rtype = operandType (IC_RIGHT (ic));
8182 operand *right = IC_RIGHT (ic);
8185 D(emitcode(";", "genCast"));
8187 /* if they are equivalent then do nothing */
8188 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8191 aopOp (right, ic, FALSE);
8192 aopOp (result, ic, FALSE);
8194 /* if the result is a bit */
8195 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8196 if (IS_BITVAR(OP_SYMBOL(result)->type))
8198 /* if the right size is a literal then
8199 we know what the value is */
8200 if (AOP_TYPE (right) == AOP_LIT)
8202 if (((int) operandLitValue (right)))
8203 aopPut (AOP (result), one, 0);
8205 aopPut (AOP (result), zero, 0);
8210 /* the right is also a bit variable */
8211 if (AOP_TYPE (right) == AOP_CRY)
8213 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8214 aopPut (AOP (result), "c", 0);
8220 aopPut (AOP (result), "a", 0);
8224 /* if they are the same size : or less */
8225 if (AOP_SIZE (result) <= AOP_SIZE (right))
8228 /* if they are in the same place */
8229 if (sameRegs (AOP (right), AOP (result)))
8232 /* if they in different places then copy */
8233 size = AOP_SIZE (result);
8237 aopPut (AOP (result),
8238 aopGet (AOP (right), offset, FALSE, FALSE),
8246 /* if the result is of type pointer */
8251 sym_link *type = operandType (right);
8252 sym_link *etype = getSpec (type);
8254 /* pointer to generic pointer */
8255 if (IS_GENPTR (ctype))
8260 p_type = DCL_TYPE (type);
8263 if (SPEC_SCLS(etype)==S_REGISTER) {
8264 // let's assume it is a generic pointer
8267 /* we have to go by the storage class */
8268 p_type = PTR_TYPE (SPEC_OCLS (etype));
8272 /* the first two bytes are known */
8273 size = GPTRSIZE - 1;
8277 aopPut (AOP (result),
8278 aopGet (AOP (right), offset, FALSE, FALSE),
8282 /* the last byte depending on type */
8298 case PPOINTER: // what the fck is this?
8303 /* this should never happen */
8304 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8305 "got unknown pointer type");
8308 aopPut (AOP (result), l, GPTRSIZE - 1);
8312 /* just copy the pointers */
8313 size = AOP_SIZE (result);
8317 aopPut (AOP (result),
8318 aopGet (AOP (right), offset, FALSE, FALSE),
8325 /* so we now know that the size of destination is greater
8326 than the size of the source */
8327 /* we move to result for the size of source */
8328 size = AOP_SIZE (right);
8332 aopPut (AOP (result),
8333 aopGet (AOP (right), offset, FALSE, FALSE),
8338 /* now depending on the sign of the source && destination */
8339 size = AOP_SIZE (result) - AOP_SIZE (right);
8340 /* if unsigned or not an integral type */
8341 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8344 aopPut (AOP (result), zero, offset++);
8348 /* we need to extend the sign :{ */
8349 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8352 emitcode ("rlc", "a");
8353 emitcode ("subb", "a,acc");
8355 aopPut (AOP (result), "a", offset++);
8358 /* we are done hurray !!!! */
8361 freeAsmop (right, NULL, ic, TRUE);
8362 freeAsmop (result, NULL, ic, TRUE);
8366 /*-----------------------------------------------------------------*/
8367 /* genDjnz - generate decrement & jump if not zero instrucion */
8368 /*-----------------------------------------------------------------*/
8370 genDjnz (iCode * ic, iCode * ifx)
8376 /* if the if condition has a false label
8377 then we cannot save */
8381 /* if the minus is not of the form
8383 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8384 !IS_OP_LITERAL (IC_RIGHT (ic)))
8387 if (operandLitValue (IC_RIGHT (ic)) != 1)
8390 /* if the size of this greater than one then no
8392 if (getSize (operandType (IC_RESULT (ic))) > 1)
8395 /* otherwise we can save BIG */
8396 lbl = newiTempLabel (NULL);
8397 lbl1 = newiTempLabel (NULL);
8399 aopOp (IC_RESULT (ic), ic, FALSE);
8401 if (AOP_NEEDSACC(IC_RESULT(ic)))
8403 /* If the result is accessed indirectly via
8404 * the accumulator, we must explicitly write
8405 * it back after the decrement.
8407 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8409 if (strcmp(rByte, "a"))
8411 /* Something is hopelessly wrong */
8412 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8413 __FILE__, __LINE__);
8414 /* We can just give up; the generated code will be inefficient,
8417 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8420 emitcode ("dec", "%s", rByte);
8421 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8422 emitcode ("jnz", "%05d$", lbl->key + 100);
8424 else if (IS_AOP_PREG (IC_RESULT (ic)))
8426 emitcode ("dec", "%s",
8427 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8428 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8429 emitcode ("jnz", "%05d$", lbl->key + 100);
8433 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8436 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8437 emitcode ("", "%05d$:", lbl->key + 100);
8438 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8439 emitcode ("", "%05d$:", lbl1->key + 100);
8441 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8446 /*-----------------------------------------------------------------*/
8447 /* genReceive - generate code for a receive iCode */
8448 /*-----------------------------------------------------------------*/
8450 genReceive (iCode * ic)
8452 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8453 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8454 IS_TRUE_SYMOP (IC_RESULT (ic))))
8457 int size = getSize (operandType (IC_RESULT (ic)));
8458 int offset = fReturnSizeMCS51 - size;
8461 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8462 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8465 aopOp (IC_RESULT (ic), ic, FALSE);
8466 size = AOP_SIZE (IC_RESULT (ic));
8470 emitcode ("pop", "acc");
8471 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8478 aopOp (IC_RESULT (ic), ic, FALSE);
8480 assignResultValue (IC_RESULT (ic));
8483 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8486 /*-----------------------------------------------------------------*/
8487 /* gen51AggregateAssign - copy complete array's or structures */
8488 /*-----------------------------------------------------------------*/
8489 void gen51AggregateAssign(iCode *ic) {
8490 operand *left=IC_LEFT(ic);
8491 operand *right=IC_RIGHT(ic);
8492 char *fromName=OP_SYMBOL(right)->rname;
8493 char *toName=OP_SYMBOL(left)->rname;
8494 int fromSize=getSize(OP_SYMBOL(right)->type);
8495 int toSize=getSize(OP_SYMBOL(left)->type);
8498 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8499 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8500 // well, this code isn't used yet from anywhere else as for initialising
8501 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8505 if (fromSize!=toSize) {
8506 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8507 ic->filename, ic->lineno);
8512 // use the generic memcpy() for now
8513 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8514 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8515 emitcode ("mov", "a,#%s", fromName);
8516 emitcode ("movx", "@dptr,a");
8517 emitcode ("inc", "dptr");
8518 emitcode ("mov", "a,#(%s>>8)", fromName);
8519 emitcode ("movx", "@dptr,a");
8520 emitcode ("inc", "dptr");
8521 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8522 emitcode ("movx", "@dptr,a");
8523 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8524 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8525 emitcode ("movx", "@dptr,a");
8526 emitcode ("inc", "dptr");
8527 emitcode ("mov", "a,#(%d>>8)", count);
8528 emitcode ("movx", "@dptr,a");
8529 emitcode ("mov", "dptr,#%s", toName);
8530 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8531 emitcode ("lcall", "_memcpy");
8533 // more efficient, but will require the native_memcpy_cs2xs
8534 emitcode ("mov", "r0,#%s", fromName);
8535 emitcode ("mov", "r1,#(%s>>8)", fromName);
8536 emitcode ("mov", "r2,#%s", toName);
8537 emitcode ("mov", "r3,#(%s>>8)", toName);
8538 emitcode ("mov", "r4,#%d", count);
8539 emitcode ("mov", "r5,#(%d>>8)", count);
8540 emitcode ("lcall", "_native_memcpy_cs2xs");
8544 /*-----------------------------------------------------------------*/
8545 /* gen51Code - generate code for 8051 based controllers */
8546 /*-----------------------------------------------------------------*/
8548 gen51Code (iCode * lic)
8553 lineHead = lineCurr = NULL;
8555 /* print the allocation information */
8557 printAllocInfo (currFunc, codeOutFile);
8558 /* if debug information required */
8559 /* if (options.debug && currFunc) { */
8560 if (options.debug && currFunc)
8562 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8564 if (IS_STATIC (currFunc->etype))
8565 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8567 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8570 /* stack pointer name */
8571 if (options.useXstack)
8577 for (ic = lic; ic; ic = ic->next)
8580 if (cln != ic->lineno)
8585 emitcode ("", "C$%s$%d$%d$%d ==.",
8586 FileBaseName (ic->filename), ic->lineno,
8587 ic->level, ic->block);
8590 emitcode (";", "%s %d", ic->filename, ic->lineno);
8593 /* if the result is marked as
8594 spilt and rematerializable or code for
8595 this has already been generated then
8597 if (resultRemat (ic) || ic->generated)
8600 /* depending on the operation */
8620 /* IPOP happens only when trying to restore a
8621 spilt live range, if there is an ifx statement
8622 following this pop then the if statement might
8623 be using some of the registers being popped which
8624 would destory the contents of the register so
8625 we need to check for this condition and handle it */
8627 ic->next->op == IFX &&
8628 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8629 genIfx (ic->next, ic);
8647 genEndFunction (ic);
8667 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8684 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8688 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8695 /* note these two are xlated by algebraic equivalence
8696 during parsing SDCC.y */
8697 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8698 "got '>=' or '<=' shouldn't have come here");
8702 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8714 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8718 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8722 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8749 case GET_VALUE_AT_ADDRESS:
8750 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8754 if (POINTER_SET (ic))
8755 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8781 addSet (&_G.sendSet, ic);
8785 gen51AggregateAssign(ic);
8794 /* now we are ready to call the
8795 peep hole optimizer */
8796 if (!options.nopeep)
8797 peepHole (&lineHead);
8799 /* now do the actual printing */
8800 printLine (lineHead, codeOutFile);