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 0 // one of them can be a sloc shared with the result
3424 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3426 if (getSize(operandType(left)) == 1 &&
3427 getSize(operandType(right)) == 1)
3430 genMultOneByte (left, right, result);
3434 /* should have been converted to function call */
3435 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3436 getSize(OP_SYMBOL(right)->type));
3440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3441 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3442 freeAsmop (result, NULL, ic, TRUE);
3445 /*-----------------------------------------------------------------*/
3446 /* genDivbits :- division of bits */
3447 /*-----------------------------------------------------------------*/
3449 genDivbits (operand * left,
3456 /* the result must be bit */
3457 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3458 l = aopGet (AOP (left), 0, FALSE, FALSE);
3462 emitcode ("div", "ab");
3463 emitcode ("rrc", "a");
3464 aopPut (AOP (result), "c", 0);
3467 /*-----------------------------------------------------------------*/
3468 /* genDivOneByte : 8 bit division */
3469 /*-----------------------------------------------------------------*/
3471 genDivOneByte (operand * left,
3475 sym_link *opetype = operandType (result);
3480 size = AOP_SIZE (result) - 1;
3482 /* signed or unsigned */
3483 if (SPEC_USIGN (opetype))
3485 /* unsigned is easy */
3486 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3487 l = aopGet (AOP (left), 0, FALSE, FALSE);
3489 emitcode ("div", "ab");
3490 aopPut (AOP (result), "a", 0);
3492 aopPut (AOP (result), zero, offset++);
3496 /* signed is a little bit more difficult */
3498 /* save the signs of the operands */
3499 l = aopGet (AOP (left), 0, FALSE, FALSE);
3501 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3502 emitcode ("push", "acc"); /* save it on the stack */
3504 /* now sign adjust for both left & right */
3505 l = aopGet (AOP (right), 0, FALSE, FALSE);
3507 lbl = newiTempLabel (NULL);
3508 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3509 emitcode ("cpl", "a");
3510 emitcode ("inc", "a");
3511 emitcode ("", "%05d$:", (lbl->key + 100));
3512 emitcode ("mov", "b,a");
3514 /* sign adjust left side */
3515 l = aopGet (AOP (left), 0, FALSE, FALSE);
3518 lbl = newiTempLabel (NULL);
3519 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3520 emitcode ("cpl", "a");
3521 emitcode ("inc", "a");
3522 emitcode ("", "%05d$:", (lbl->key + 100));
3524 /* now the division */
3525 emitcode ("div", "ab");
3526 /* we are interested in the lower order
3528 emitcode ("mov", "b,a");
3529 lbl = newiTempLabel (NULL);
3530 emitcode ("pop", "acc");
3531 /* if there was an over flow we don't
3532 adjust the sign of the result */
3533 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3534 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3536 emitcode ("clr", "a");
3537 emitcode ("subb", "a,b");
3538 emitcode ("mov", "b,a");
3539 emitcode ("", "%05d$:", (lbl->key + 100));
3541 /* now we are done */
3542 aopPut (AOP (result), "b", 0);
3545 emitcode ("mov", "c,b.7");
3546 emitcode ("subb", "a,acc");
3549 aopPut (AOP (result), "a", offset++);
3553 /*-----------------------------------------------------------------*/
3554 /* genDiv - generates code for division */
3555 /*-----------------------------------------------------------------*/
3559 operand *left = IC_LEFT (ic);
3560 operand *right = IC_RIGHT (ic);
3561 operand *result = IC_RESULT (ic);
3563 /* assign the amsops */
3564 aopOp (left, ic, FALSE);
3565 aopOp (right, ic, FALSE);
3566 aopOp (result, ic, TRUE);
3568 /* special cases first */
3570 if (AOP_TYPE (left) == AOP_CRY &&
3571 AOP_TYPE (right) == AOP_CRY)
3573 genDivbits (left, right, result);
3577 /* if both are of size == 1 */
3578 if (AOP_SIZE (left) == 1 &&
3579 AOP_SIZE (right) == 1)
3581 genDivOneByte (left, right, result);
3585 /* should have been converted to function call */
3588 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3590 freeAsmop (result, NULL, ic, TRUE);
3593 /*-----------------------------------------------------------------*/
3594 /* genModbits :- modulus of bits */
3595 /*-----------------------------------------------------------------*/
3597 genModbits (operand * left,
3604 /* the result must be bit */
3605 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3606 l = aopGet (AOP (left), 0, FALSE, FALSE);
3610 emitcode ("div", "ab");
3611 emitcode ("mov", "a,b");
3612 emitcode ("rrc", "a");
3613 aopPut (AOP (result), "c", 0);
3616 /*-----------------------------------------------------------------*/
3617 /* genModOneByte : 8 bit modulus */
3618 /*-----------------------------------------------------------------*/
3620 genModOneByte (operand * left,
3624 sym_link *opetype = operandType (result);
3628 /* signed or unsigned */
3629 if (SPEC_USIGN (opetype))
3631 /* unsigned is easy */
3632 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3633 l = aopGet (AOP (left), 0, FALSE, FALSE);
3635 emitcode ("div", "ab");
3636 aopPut (AOP (result), "b", 0);
3640 /* signed is a little bit more difficult */
3642 /* save the signs of the operands */
3643 l = aopGet (AOP (left), 0, FALSE, FALSE);
3646 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3647 emitcode ("push", "acc"); /* save it on the stack */
3649 /* now sign adjust for both left & right */
3650 l = aopGet (AOP (right), 0, FALSE, FALSE);
3653 lbl = newiTempLabel (NULL);
3654 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3655 emitcode ("cpl", "a");
3656 emitcode ("inc", "a");
3657 emitcode ("", "%05d$:", (lbl->key + 100));
3658 emitcode ("mov", "b,a");
3660 /* sign adjust left side */
3661 l = aopGet (AOP (left), 0, FALSE, FALSE);
3664 lbl = newiTempLabel (NULL);
3665 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3666 emitcode ("cpl", "a");
3667 emitcode ("inc", "a");
3668 emitcode ("", "%05d$:", (lbl->key + 100));
3670 /* now the multiplication */
3671 emitcode ("div", "ab");
3672 /* we are interested in the lower order
3674 lbl = newiTempLabel (NULL);
3675 emitcode ("pop", "acc");
3676 /* if there was an over flow we don't
3677 adjust the sign of the result */
3678 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3679 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3681 emitcode ("clr", "a");
3682 emitcode ("subb", "a,b");
3683 emitcode ("mov", "b,a");
3684 emitcode ("", "%05d$:", (lbl->key + 100));
3686 /* now we are done */
3687 aopPut (AOP (result), "b", 0);
3691 /*-----------------------------------------------------------------*/
3692 /* genMod - generates code for division */
3693 /*-----------------------------------------------------------------*/
3697 operand *left = IC_LEFT (ic);
3698 operand *right = IC_RIGHT (ic);
3699 operand *result = IC_RESULT (ic);
3701 /* assign the amsops */
3702 aopOp (left, ic, FALSE);
3703 aopOp (right, ic, FALSE);
3704 aopOp (result, ic, TRUE);
3706 /* special cases first */
3708 if (AOP_TYPE (left) == AOP_CRY &&
3709 AOP_TYPE (right) == AOP_CRY)
3711 genModbits (left, right, result);
3715 /* if both are of size == 1 */
3716 if (AOP_SIZE (left) == 1 &&
3717 AOP_SIZE (right) == 1)
3719 genModOneByte (left, right, result);
3723 /* should have been converted to function call */
3727 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3728 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (result, NULL, ic, TRUE);
3732 /*-----------------------------------------------------------------*/
3733 /* genIfxJump :- will create a jump depending on the ifx */
3734 /*-----------------------------------------------------------------*/
3736 genIfxJump (iCode * ic, char *jval)
3739 symbol *tlbl = newiTempLabel (NULL);
3742 /* if true label then we jump if condition
3746 jlbl = IC_TRUE (ic);
3747 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3748 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3752 /* false label is present */
3753 jlbl = IC_FALSE (ic);
3754 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3755 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3757 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3758 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3760 emitcode (inst, "%05d$", tlbl->key + 100);
3761 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3762 emitcode ("", "%05d$:", tlbl->key + 100);
3764 /* mark the icode as generated */
3768 /*-----------------------------------------------------------------*/
3769 /* genCmp :- greater or less than comparison */
3770 /*-----------------------------------------------------------------*/
3772 genCmp (operand * left, operand * right,
3773 operand * result, iCode * ifx, int sign, iCode *ic)
3775 int size, offset = 0;
3776 unsigned long lit = 0L;
3778 /* if left & right are bit variables */
3779 if (AOP_TYPE (left) == AOP_CRY &&
3780 AOP_TYPE (right) == AOP_CRY)
3782 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3783 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3787 /* subtract right from left if at the
3788 end the carry flag is set then we know that
3789 left is greater than right */
3790 size = max (AOP_SIZE (left), AOP_SIZE (right));
3792 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3793 if ((size == 1) && !sign &&
3794 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3796 symbol *lbl = newiTempLabel (NULL);
3797 emitcode ("cjne", "%s,%s,%05d$",
3798 aopGet (AOP (left), offset, FALSE, FALSE),
3799 aopGet (AOP (right), offset, FALSE, FALSE),
3801 emitcode ("", "%05d$:", lbl->key + 100);
3805 if (AOP_TYPE (right) == AOP_LIT)
3807 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3808 /* optimize if(x < 0) or if(x >= 0) */
3817 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3818 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3820 genIfxJump (ifx, "acc.7");
3824 emitcode ("rlc", "a");
3832 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3833 if (sign && size == 0)
3835 emitcode ("xrl", "a,#0x80");
3836 if (AOP_TYPE (right) == AOP_LIT)
3838 unsigned long lit = (unsigned long)
3839 floatFromVal (AOP (right)->aopu.aop_lit);
3840 emitcode ("subb", "a,#0x%02x",
3841 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3845 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3846 emitcode ("xrl", "b,#0x80");
3847 emitcode ("subb", "a,b");
3851 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3857 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3858 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3859 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3865 /* if the result is used in the next
3866 ifx conditional branch then generate
3867 code a little differently */
3869 genIfxJump (ifx, "c");
3872 /* leave the result in acc */
3876 /*-----------------------------------------------------------------*/
3877 /* genCmpGt :- greater than comparison */
3878 /*-----------------------------------------------------------------*/
3880 genCmpGt (iCode * ic, iCode * ifx)
3882 operand *left, *right, *result;
3883 sym_link *letype, *retype;
3886 left = IC_LEFT (ic);
3887 right = IC_RIGHT (ic);
3888 result = IC_RESULT (ic);
3890 letype = getSpec (operandType (left));
3891 retype = getSpec (operandType (right));
3892 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3893 /* assign the amsops */
3894 aopOp (left, ic, FALSE);
3895 aopOp (right, ic, FALSE);
3896 aopOp (result, ic, TRUE);
3898 genCmp (right, left, result, ifx, sign,ic);
3900 freeAsmop (result, NULL, ic, TRUE);
3903 /*-----------------------------------------------------------------*/
3904 /* genCmpLt - less than comparisons */
3905 /*-----------------------------------------------------------------*/
3907 genCmpLt (iCode * ic, iCode * ifx)
3909 operand *left, *right, *result;
3910 sym_link *letype, *retype;
3913 left = IC_LEFT (ic);
3914 right = IC_RIGHT (ic);
3915 result = IC_RESULT (ic);
3917 letype = getSpec (operandType (left));
3918 retype = getSpec (operandType (right));
3919 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3921 /* assign the amsops */
3922 aopOp (left, ic, FALSE);
3923 aopOp (right, ic, FALSE);
3924 aopOp (result, ic, TRUE);
3926 genCmp (left, right, result, ifx, sign,ic);
3928 freeAsmop (result, NULL, ic, TRUE);
3931 /*-----------------------------------------------------------------*/
3932 /* gencjneshort - compare and jump if not equal */
3933 /*-----------------------------------------------------------------*/
3935 gencjneshort (operand * left, operand * right, symbol * lbl)
3937 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3939 unsigned long lit = 0L;
3941 /* if the left side is a literal or
3942 if the right is in a pointer register and left
3944 if ((AOP_TYPE (left) == AOP_LIT) ||
3945 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3951 if (AOP_TYPE (right) == AOP_LIT)
3952 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3954 /* if the right side is a literal then anything goes */
3955 if (AOP_TYPE (right) == AOP_LIT &&
3956 AOP_TYPE (left) != AOP_DIR)
3960 emitcode ("cjne", "%s,%s,%05d$",
3961 aopGet (AOP (left), offset, FALSE, FALSE),
3962 aopGet (AOP (right), offset, FALSE, FALSE),
3968 /* if the right side is in a register or in direct space or
3969 if the left is a pointer register & right is not */
3970 else if (AOP_TYPE (right) == AOP_REG ||
3971 AOP_TYPE (right) == AOP_DIR ||
3972 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3973 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3977 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3978 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3979 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3980 emitcode ("jnz", "%05d$", lbl->key + 100);
3982 emitcode ("cjne", "a,%s,%05d$",
3983 aopGet (AOP (right), offset, FALSE, TRUE),
3990 /* right is a pointer reg need both a & b */
3993 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3994 if (strcmp (l, "b"))
3995 emitcode ("mov", "b,%s", l);
3996 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3997 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4003 /*-----------------------------------------------------------------*/
4004 /* gencjne - compare and jump if not equal */
4005 /*-----------------------------------------------------------------*/
4007 gencjne (operand * left, operand * right, symbol * lbl)
4009 symbol *tlbl = newiTempLabel (NULL);
4011 gencjneshort (left, right, lbl);
4013 emitcode ("mov", "a,%s", one);
4014 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4015 emitcode ("", "%05d$:", lbl->key + 100);
4016 emitcode ("clr", "a");
4017 emitcode ("", "%05d$:", tlbl->key + 100);
4020 /*-----------------------------------------------------------------*/
4021 /* genCmpEq - generates code for equal to */
4022 /*-----------------------------------------------------------------*/
4024 genCmpEq (iCode * ic, iCode * ifx)
4026 operand *left, *right, *result;
4028 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4029 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4030 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4032 /* if literal, literal on the right or
4033 if the right is in a pointer register and left
4035 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4036 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4038 operand *t = IC_RIGHT (ic);
4039 IC_RIGHT (ic) = IC_LEFT (ic);
4043 if (ifx && !AOP_SIZE (result))
4046 /* if they are both bit variables */
4047 if (AOP_TYPE (left) == AOP_CRY &&
4048 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4050 if (AOP_TYPE (right) == AOP_LIT)
4052 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056 emitcode ("cpl", "c");
4060 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4064 emitcode ("clr", "c");
4066 /* AOP_TYPE(right) == AOP_CRY */
4070 symbol *lbl = newiTempLabel (NULL);
4071 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4072 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4073 emitcode ("cpl", "c");
4074 emitcode ("", "%05d$:", (lbl->key + 100));
4076 /* if true label then we jump if condition
4078 tlbl = newiTempLabel (NULL);
4081 emitcode ("jnc", "%05d$", tlbl->key + 100);
4082 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4086 emitcode ("jc", "%05d$", tlbl->key + 100);
4087 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4089 emitcode ("", "%05d$:", tlbl->key + 100);
4093 tlbl = newiTempLabel (NULL);
4094 gencjneshort (left, right, tlbl);
4097 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4098 emitcode ("", "%05d$:", tlbl->key + 100);
4102 symbol *lbl = newiTempLabel (NULL);
4103 emitcode ("sjmp", "%05d$", lbl->key + 100);
4104 emitcode ("", "%05d$:", tlbl->key + 100);
4105 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4106 emitcode ("", "%05d$:", lbl->key + 100);
4109 /* mark the icode as generated */
4114 /* if they are both bit variables */
4115 if (AOP_TYPE (left) == AOP_CRY &&
4116 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4118 if (AOP_TYPE (right) == AOP_LIT)
4120 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4123 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4124 emitcode ("cpl", "c");
4128 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4132 emitcode ("clr", "c");
4134 /* AOP_TYPE(right) == AOP_CRY */
4138 symbol *lbl = newiTempLabel (NULL);
4139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4140 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4141 emitcode ("cpl", "c");
4142 emitcode ("", "%05d$:", (lbl->key + 100));
4145 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4152 genIfxJump (ifx, "c");
4155 /* if the result is used in an arithmetic operation
4156 then put the result in place */
4161 gencjne (left, right, newiTempLabel (NULL));
4162 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4164 aopPut (AOP (result), "a", 0);
4169 genIfxJump (ifx, "a");
4172 /* if the result is used in an arithmetic operation
4173 then put the result in place */
4174 if (AOP_TYPE (result) != AOP_CRY)
4176 /* leave the result in acc */
4180 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4181 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4182 freeAsmop (result, NULL, ic, TRUE);
4185 /*-----------------------------------------------------------------*/
4186 /* ifxForOp - returns the icode containing the ifx for operand */
4187 /*-----------------------------------------------------------------*/
4189 ifxForOp (operand * op, iCode * ic)
4191 /* if true symbol then needs to be assigned */
4192 if (IS_TRUE_SYMOP (op))
4195 /* if this has register type condition and
4196 the next instruction is ifx with the same operand
4197 and live to of the operand is upto the ifx only then */
4199 ic->next->op == IFX &&
4200 IC_COND (ic->next)->key == op->key &&
4201 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4207 /*-----------------------------------------------------------------*/
4208 /* hasInc - operand is incremented before any other use */
4209 /*-----------------------------------------------------------------*/
4211 hasInc (operand *op, iCode *ic)
4213 sym_link *type = operandType(op);
4214 sym_link *retype = getSpec (type);
4215 iCode *lic = ic->next;
4218 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4219 if (!IS_SYMOP(op)) return NULL;
4221 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4222 isize = getSize(type->next);
4224 /* if operand of the form op = op + <sizeof *op> */
4225 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4226 isOperandEqual(IC_RESULT(lic),op) &&
4227 isOperandLiteral(IC_RIGHT(lic)) &&
4228 operandLitValue(IC_RIGHT(lic)) == isize) {
4231 /* if the operand used or deffed */
4232 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4240 /*-----------------------------------------------------------------*/
4241 /* genAndOp - for && operation */
4242 /*-----------------------------------------------------------------*/
4244 genAndOp (iCode * ic)
4246 operand *left, *right, *result;
4249 /* note here that && operations that are in an
4250 if statement are taken away by backPatchLabels
4251 only those used in arthmetic operations remain */
4252 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4253 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4254 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4256 /* if both are bit variables */
4257 if (AOP_TYPE (left) == AOP_CRY &&
4258 AOP_TYPE (right) == AOP_CRY)
4260 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4261 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4266 tlbl = newiTempLabel (NULL);
4268 emitcode ("jz", "%05d$", tlbl->key + 100);
4270 emitcode ("", "%05d$:", tlbl->key + 100);
4274 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4275 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4276 freeAsmop (result, NULL, ic, TRUE);
4280 /*-----------------------------------------------------------------*/
4281 /* genOrOp - for || operation */
4282 /*-----------------------------------------------------------------*/
4284 genOrOp (iCode * ic)
4286 operand *left, *right, *result;
4289 /* note here that || operations that are in an
4290 if statement are taken away by backPatchLabels
4291 only those used in arthmetic operations remain */
4292 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4293 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4294 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4296 /* if both are bit variables */
4297 if (AOP_TYPE (left) == AOP_CRY &&
4298 AOP_TYPE (right) == AOP_CRY)
4300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4301 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4306 tlbl = newiTempLabel (NULL);
4308 emitcode ("jnz", "%05d$", tlbl->key + 100);
4310 emitcode ("", "%05d$:", tlbl->key + 100);
4314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4316 freeAsmop (result, NULL, ic, TRUE);
4319 /*-----------------------------------------------------------------*/
4320 /* isLiteralBit - test if lit == 2^n */
4321 /*-----------------------------------------------------------------*/
4323 isLiteralBit (unsigned long lit)
4325 unsigned long pw[32] =
4326 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4327 0x100L, 0x200L, 0x400L, 0x800L,
4328 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4329 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4330 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4331 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4332 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4335 for (idx = 0; idx < 32; idx++)
4341 /*-----------------------------------------------------------------*/
4342 /* continueIfTrue - */
4343 /*-----------------------------------------------------------------*/
4345 continueIfTrue (iCode * ic)
4348 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4352 /*-----------------------------------------------------------------*/
4354 /*-----------------------------------------------------------------*/
4356 jumpIfTrue (iCode * ic)
4359 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4363 /*-----------------------------------------------------------------*/
4364 /* jmpTrueOrFalse - */
4365 /*-----------------------------------------------------------------*/
4367 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4369 // ugly but optimized by peephole
4372 symbol *nlbl = newiTempLabel (NULL);
4373 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4374 emitcode ("", "%05d$:", tlbl->key + 100);
4375 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4376 emitcode ("", "%05d$:", nlbl->key + 100);
4380 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4381 emitcode ("", "%05d$:", tlbl->key + 100);
4386 /*-----------------------------------------------------------------*/
4387 /* genAnd - code for and */
4388 /*-----------------------------------------------------------------*/
4390 genAnd (iCode * ic, iCode * ifx)
4392 operand *left, *right, *result;
4393 int size, offset = 0;
4394 unsigned long lit = 0L;
4398 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4399 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4400 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4403 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4405 AOP_TYPE (left), AOP_TYPE (right));
4406 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4408 AOP_SIZE (left), AOP_SIZE (right));
4411 /* if left is a literal & right is not then exchange them */
4412 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4413 AOP_NEEDSACC (left))
4415 operand *tmp = right;
4420 /* if result = right then exchange them */
4421 if (sameRegs (AOP (result), AOP (right)))
4423 operand *tmp = right;
4428 /* if right is bit then exchange them */
4429 if (AOP_TYPE (right) == AOP_CRY &&
4430 AOP_TYPE (left) != AOP_CRY)
4432 operand *tmp = right;
4436 if (AOP_TYPE (right) == AOP_LIT)
4437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4439 size = AOP_SIZE (result);
4442 // result = bit & yy;
4443 if (AOP_TYPE (left) == AOP_CRY)
4445 // c = bit & literal;
4446 if (AOP_TYPE (right) == AOP_LIT)
4450 if (size && sameRegs (AOP (result), AOP (left)))
4453 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4458 if (size && (AOP_TYPE (result) == AOP_CRY))
4460 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4463 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4468 emitcode ("clr", "c");
4473 if (AOP_TYPE (right) == AOP_CRY)
4476 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4477 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4482 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4484 emitcode ("rrc", "a");
4485 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4493 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4494 genIfxJump (ifx, "c");
4498 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4499 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4500 if ((AOP_TYPE (right) == AOP_LIT) &&
4501 (AOP_TYPE (result) == AOP_CRY) &&
4502 (AOP_TYPE (left) != AOP_CRY))
4504 int posbit = isLiteralBit (lit);
4509 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4512 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4518 sprintf (buffer, "acc.%d", posbit & 0x07);
4519 genIfxJump (ifx, buffer);
4526 symbol *tlbl = newiTempLabel (NULL);
4527 int sizel = AOP_SIZE (left);
4529 emitcode ("setb", "c");
4532 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4534 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4536 if ((posbit = isLiteralBit (bytelit)) != 0)
4537 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4540 if (bytelit != 0x0FFL)
4541 emitcode ("anl", "a,%s",
4542 aopGet (AOP (right), offset, FALSE, TRUE));
4543 emitcode ("jnz", "%05d$", tlbl->key + 100);
4548 // bit = left & literal
4551 emitcode ("clr", "c");
4552 emitcode ("", "%05d$:", tlbl->key + 100);
4554 // if(left & literal)
4558 jmpTrueOrFalse (ifx, tlbl);
4566 /* if left is same as result */
4567 if (sameRegs (AOP (result), AOP (left)))
4569 for (; size--; offset++)
4571 if (AOP_TYPE (right) == AOP_LIT)
4573 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4575 else if (bytelit == 0)
4576 aopPut (AOP (result), zero, offset);
4577 else if (IS_AOP_PREG (result))
4579 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4580 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4581 aopPut (AOP (result), "a", offset);
4584 emitcode ("anl", "%s,%s",
4585 aopGet (AOP (left), offset, FALSE, TRUE),
4586 aopGet (AOP (right), offset, FALSE, FALSE));
4590 if (AOP_TYPE (left) == AOP_ACC)
4591 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4594 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4595 if (IS_AOP_PREG (result))
4597 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4598 aopPut (AOP (result), "a", offset);
4602 emitcode ("anl", "%s,a",
4603 aopGet (AOP (left), offset, FALSE, TRUE));
4610 // left & result in different registers
4611 if (AOP_TYPE (result) == AOP_CRY)
4614 // if(size), result in bit
4615 // if(!size && ifx), conditional oper: if(left & right)
4616 symbol *tlbl = newiTempLabel (NULL);
4617 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4619 emitcode ("setb", "c");
4622 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4623 emitcode ("anl", "a,%s",
4624 aopGet (AOP (right), offset, FALSE, FALSE));
4626 if (AOP_TYPE(left)==AOP_ACC) {
4627 emitcode("mov", "b,a");
4628 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4629 emitcode("anl", "a,b");
4631 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4632 emitcode ("anl", "a,%s",
4633 aopGet (AOP (left), offset, FALSE, FALSE));
4636 emitcode ("jnz", "%05d$", tlbl->key + 100);
4642 emitcode ("", "%05d$:", tlbl->key + 100);
4646 jmpTrueOrFalse (ifx, tlbl);
4650 for (; (size--); offset++)
4653 // result = left & right
4654 if (AOP_TYPE (right) == AOP_LIT)
4656 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4658 aopPut (AOP (result),
4659 aopGet (AOP (left), offset, FALSE, FALSE),
4663 else if (bytelit == 0)
4665 aopPut (AOP (result), zero, offset);
4669 // faster than result <- left, anl result,right
4670 // and better if result is SFR
4671 if (AOP_TYPE (left) == AOP_ACC)
4672 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4675 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4676 emitcode ("anl", "a,%s",
4677 aopGet (AOP (left), offset, FALSE, FALSE));
4679 aopPut (AOP (result), "a", offset);
4685 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (result, NULL, ic, TRUE);
4690 /*-----------------------------------------------------------------*/
4691 /* genOr - code for or */
4692 /*-----------------------------------------------------------------*/
4694 genOr (iCode * ic, iCode * ifx)
4696 operand *left, *right, *result;
4697 int size, offset = 0;
4698 unsigned long lit = 0L;
4700 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4701 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4702 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4705 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4707 AOP_TYPE (left), AOP_TYPE (right));
4708 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4710 AOP_SIZE (left), AOP_SIZE (right));
4713 /* if left is a literal & right is not then exchange them */
4714 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4715 AOP_NEEDSACC (left))
4717 operand *tmp = right;
4722 /* if result = right then exchange them */
4723 if (sameRegs (AOP (result), AOP (right)))
4725 operand *tmp = right;
4730 /* if right is bit then exchange them */
4731 if (AOP_TYPE (right) == AOP_CRY &&
4732 AOP_TYPE (left) != AOP_CRY)
4734 operand *tmp = right;
4738 if (AOP_TYPE (right) == AOP_LIT)
4739 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4741 size = AOP_SIZE (result);
4745 if (AOP_TYPE (left) == AOP_CRY)
4747 if (AOP_TYPE (right) == AOP_LIT)
4749 // c = bit & literal;
4752 // lit != 0 => result = 1
4753 if (AOP_TYPE (result) == AOP_CRY)
4756 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4758 continueIfTrue (ifx);
4761 emitcode ("setb", "c");
4765 // lit == 0 => result = left
4766 if (size && sameRegs (AOP (result), AOP (left)))
4768 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4773 if (AOP_TYPE (right) == AOP_CRY)
4776 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4777 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4782 symbol *tlbl = newiTempLabel (NULL);
4783 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4784 emitcode ("setb", "c");
4785 emitcode ("jb", "%s,%05d$",
4786 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4788 emitcode ("jnz", "%05d$", tlbl->key + 100);
4789 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4791 jmpTrueOrFalse (ifx, tlbl);
4797 emitcode ("", "%05d$:", tlbl->key + 100);
4806 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4807 genIfxJump (ifx, "c");
4811 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4812 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4813 if ((AOP_TYPE (right) == AOP_LIT) &&
4814 (AOP_TYPE (result) == AOP_CRY) &&
4815 (AOP_TYPE (left) != AOP_CRY))
4821 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4823 continueIfTrue (ifx);
4828 // lit = 0, result = boolean(left)
4830 emitcode ("setb", "c");
4834 symbol *tlbl = newiTempLabel (NULL);
4835 emitcode ("jnz", "%05d$", tlbl->key + 100);
4837 emitcode ("", "%05d$:", tlbl->key + 100);
4841 genIfxJump (ifx, "a");
4849 /* if left is same as result */
4850 if (sameRegs (AOP (result), AOP (left)))
4852 for (; size--; offset++)
4854 if (AOP_TYPE (right) == AOP_LIT)
4856 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4858 else if (IS_AOP_PREG (left))
4860 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4861 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4862 aopPut (AOP (result), "a", offset);
4865 emitcode ("orl", "%s,%s",
4866 aopGet (AOP (left), offset, FALSE, TRUE),
4867 aopGet (AOP (right), offset, FALSE, FALSE));
4871 if (AOP_TYPE (left) == AOP_ACC)
4872 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4875 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4876 if (IS_AOP_PREG (left))
4878 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4879 aopPut (AOP (result), "a", offset);
4882 emitcode ("orl", "%s,a",
4883 aopGet (AOP (left), offset, FALSE, TRUE));
4890 // left & result in different registers
4891 if (AOP_TYPE (result) == AOP_CRY)
4894 // if(size), result in bit
4895 // if(!size && ifx), conditional oper: if(left | right)
4896 symbol *tlbl = newiTempLabel (NULL);
4897 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4899 emitcode ("setb", "c");
4902 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4903 emitcode ("orl", "a,%s",
4904 aopGet (AOP (right), offset, FALSE, FALSE));
4906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4907 emitcode ("orl", "a,%s",
4908 aopGet (AOP (left), offset, FALSE, FALSE));
4910 emitcode ("jnz", "%05d$", tlbl->key + 100);
4916 emitcode ("", "%05d$:", tlbl->key + 100);
4920 jmpTrueOrFalse (ifx, tlbl);
4923 for (; (size--); offset++)
4926 // result = left & right
4927 if (AOP_TYPE (right) == AOP_LIT)
4929 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4931 aopPut (AOP (result),
4932 aopGet (AOP (left), offset, FALSE, FALSE),
4937 // faster than result <- left, anl result,right
4938 // and better if result is SFR
4939 if (AOP_TYPE (left) == AOP_ACC)
4940 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4943 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4944 emitcode ("orl", "a,%s",
4945 aopGet (AOP (left), offset, FALSE, FALSE));
4947 aopPut (AOP (result), "a", offset);
4952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4954 freeAsmop (result, NULL, ic, TRUE);
4957 /*-----------------------------------------------------------------*/
4958 /* genXor - code for xclusive or */
4959 /*-----------------------------------------------------------------*/
4961 genXor (iCode * ic, iCode * ifx)
4963 operand *left, *right, *result;
4964 int size, offset = 0;
4965 unsigned long lit = 0L;
4967 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4968 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4969 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4972 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4974 AOP_TYPE (left), AOP_TYPE (right));
4975 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4977 AOP_SIZE (left), AOP_SIZE (right));
4980 /* if left is a literal & right is not ||
4981 if left needs acc & right does not */
4982 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4983 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4985 operand *tmp = right;
4990 /* if result = right then exchange them */
4991 if (sameRegs (AOP (result), AOP (right)))
4993 operand *tmp = right;
4998 /* if right is bit then exchange them */
4999 if (AOP_TYPE (right) == AOP_CRY &&
5000 AOP_TYPE (left) != AOP_CRY)
5002 operand *tmp = right;
5006 if (AOP_TYPE (right) == AOP_LIT)
5007 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5009 size = AOP_SIZE (result);
5013 if (AOP_TYPE (left) == AOP_CRY)
5015 if (AOP_TYPE (right) == AOP_LIT)
5017 // c = bit & literal;
5020 // lit>>1 != 0 => result = 1
5021 if (AOP_TYPE (result) == AOP_CRY)
5024 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5026 continueIfTrue (ifx);
5029 emitcode ("setb", "c");
5036 // lit == 0, result = left
5037 if (size && sameRegs (AOP (result), AOP (left)))
5039 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5043 // lit == 1, result = not(left)
5044 if (size && sameRegs (AOP (result), AOP (left)))
5046 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5052 emitcode ("cpl", "c");
5061 symbol *tlbl = newiTempLabel (NULL);
5062 if (AOP_TYPE (right) == AOP_CRY)
5065 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5069 int sizer = AOP_SIZE (right);
5071 // if val>>1 != 0, result = 1
5072 emitcode ("setb", "c");
5075 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5077 // test the msb of the lsb
5078 emitcode ("anl", "a,#0xfe");
5079 emitcode ("jnz", "%05d$", tlbl->key + 100);
5083 emitcode ("rrc", "a");
5085 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5086 emitcode ("cpl", "c");
5087 emitcode ("", "%05d$:", (tlbl->key + 100));
5094 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5095 genIfxJump (ifx, "c");
5099 if (sameRegs (AOP (result), AOP (left)))
5101 /* if left is same as result */
5102 for (; size--; offset++)
5104 if (AOP_TYPE (right) == AOP_LIT)
5106 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5108 else if (IS_AOP_PREG (left))
5110 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5111 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5112 aopPut (AOP (result), "a", offset);
5115 emitcode ("xrl", "%s,%s",
5116 aopGet (AOP (left), offset, FALSE, TRUE),
5117 aopGet (AOP (right), offset, FALSE, FALSE));
5121 if (AOP_TYPE (left) == AOP_ACC)
5122 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5125 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5126 if (IS_AOP_PREG (left))
5128 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5129 aopPut (AOP (result), "a", offset);
5132 emitcode ("xrl", "%s,a",
5133 aopGet (AOP (left), offset, FALSE, TRUE));
5140 // left & result in different registers
5141 if (AOP_TYPE (result) == AOP_CRY)
5144 // if(size), result in bit
5145 // if(!size && ifx), conditional oper: if(left ^ right)
5146 symbol *tlbl = newiTempLabel (NULL);
5147 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5149 emitcode ("setb", "c");
5152 if ((AOP_TYPE (right) == AOP_LIT) &&
5153 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5155 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5159 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5160 emitcode ("xrl", "a,%s",
5161 aopGet (AOP (right), offset, FALSE, FALSE));
5163 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5164 emitcode ("xrl", "a,%s",
5165 aopGet (AOP (left), offset, FALSE, FALSE));
5168 emitcode ("jnz", "%05d$", tlbl->key + 100);
5174 emitcode ("", "%05d$:", tlbl->key + 100);
5178 jmpTrueOrFalse (ifx, tlbl);
5181 for (; (size--); offset++)
5184 // result = left & right
5185 if (AOP_TYPE (right) == AOP_LIT)
5187 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5189 aopPut (AOP (result),
5190 aopGet (AOP (left), offset, FALSE, FALSE),
5195 // faster than result <- left, anl result,right
5196 // and better if result is SFR
5197 if (AOP_TYPE (left) == AOP_ACC)
5198 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5202 emitcode ("xrl", "a,%s",
5203 aopGet (AOP (left), offset, FALSE, TRUE));
5205 aopPut (AOP (result), "a", offset);
5210 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5211 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5212 freeAsmop (result, NULL, ic, TRUE);
5215 /*-----------------------------------------------------------------*/
5216 /* genInline - write the inline code out */
5217 /*-----------------------------------------------------------------*/
5219 genInline (iCode * ic)
5221 char *buffer, *bp, *bp1;
5223 _G.inLine += (!options.asmpeep);
5225 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5226 strcpy (buffer, IC_INLINE (ic));
5228 /* emit each line as a code */
5253 /* emitcode("",buffer); */
5254 _G.inLine -= (!options.asmpeep);
5257 /*-----------------------------------------------------------------*/
5258 /* genRRC - rotate right with carry */
5259 /*-----------------------------------------------------------------*/
5263 operand *left, *result;
5264 int size, offset = 0;
5267 /* rotate right with carry */
5268 left = IC_LEFT (ic);
5269 result = IC_RESULT (ic);
5270 aopOp (left, ic, FALSE);
5271 aopOp (result, ic, FALSE);
5273 /* move it to the result */
5274 size = AOP_SIZE (result);
5276 if (size == 1) { /* special case for 1 byte */
5277 l = aopGet (AOP (left), offset, FALSE, FALSE);
5279 emitcode ("rr", "a");
5285 l = aopGet (AOP (left), offset, FALSE, FALSE);
5287 emitcode ("rrc", "a");
5288 if (AOP_SIZE (result) > 1)
5289 aopPut (AOP (result), "a", offset--);
5291 /* now we need to put the carry into the
5292 highest order byte of the result */
5293 if (AOP_SIZE (result) > 1)
5295 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5298 emitcode ("mov", "acc.7,c");
5300 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5301 freeAsmop (left, NULL, ic, TRUE);
5302 freeAsmop (result, NULL, ic, TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* genRLC - generate code for rotate left with carry */
5307 /*-----------------------------------------------------------------*/
5311 operand *left, *result;
5312 int size, offset = 0;
5315 /* rotate right with carry */
5316 left = IC_LEFT (ic);
5317 result = IC_RESULT (ic);
5318 aopOp (left, ic, FALSE);
5319 aopOp (result, ic, FALSE);
5321 /* move it to the result */
5322 size = AOP_SIZE (result);
5326 l = aopGet (AOP (left), offset, FALSE, FALSE);
5328 if (size == 0) { /* special case for 1 byte */
5332 emitcode ("add", "a,acc");
5333 if (AOP_SIZE (result) > 1)
5334 aopPut (AOP (result), "a", offset++);
5337 l = aopGet (AOP (left), offset, FALSE, FALSE);
5339 emitcode ("rlc", "a");
5340 if (AOP_SIZE (result) > 1)
5341 aopPut (AOP (result), "a", offset++);
5344 /* now we need to put the carry into the
5345 highest order byte of the result */
5346 if (AOP_SIZE (result) > 1)
5348 l = aopGet (AOP (result), 0, FALSE, FALSE);
5351 emitcode ("mov", "acc.0,c");
5353 aopPut (AOP (result), "a", 0);
5354 freeAsmop (left, NULL, ic, TRUE);
5355 freeAsmop (result, NULL, ic, TRUE);
5358 /*-----------------------------------------------------------------*/
5359 /* genGetHbit - generates code get highest order bit */
5360 /*-----------------------------------------------------------------*/
5362 genGetHbit (iCode * ic)
5364 operand *left, *result;
5365 left = IC_LEFT (ic);
5366 result = IC_RESULT (ic);
5367 aopOp (left, ic, FALSE);
5368 aopOp (result, ic, FALSE);
5370 /* get the highest order byte into a */
5371 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5372 if (AOP_TYPE (result) == AOP_CRY)
5374 emitcode ("rlc", "a");
5379 emitcode ("rl", "a");
5380 emitcode ("anl", "a,#0x01");
5385 freeAsmop (left, NULL, ic, TRUE);
5386 freeAsmop (result, NULL, ic, TRUE);
5389 /*-----------------------------------------------------------------*/
5390 /* AccRol - rotate left accumulator by known count */
5391 /*-----------------------------------------------------------------*/
5393 AccRol (int shCount)
5395 shCount &= 0x0007; // shCount : 0..7
5402 emitcode ("rl", "a");
5405 emitcode ("rl", "a");
5406 emitcode ("rl", "a");
5409 emitcode ("swap", "a");
5410 emitcode ("rr", "a");
5413 emitcode ("swap", "a");
5416 emitcode ("swap", "a");
5417 emitcode ("rl", "a");
5420 emitcode ("rr", "a");
5421 emitcode ("rr", "a");
5424 emitcode ("rr", "a");
5429 /*-----------------------------------------------------------------*/
5430 /* AccLsh - left shift accumulator by known count */
5431 /*-----------------------------------------------------------------*/
5433 AccLsh (int shCount)
5438 emitcode ("add", "a,acc");
5439 else if (shCount == 2)
5441 emitcode ("add", "a,acc");
5442 emitcode ("add", "a,acc");
5446 /* rotate left accumulator */
5448 /* and kill the lower order bits */
5449 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5454 /*-----------------------------------------------------------------*/
5455 /* AccRsh - right shift accumulator by known count */
5456 /*-----------------------------------------------------------------*/
5458 AccRsh (int shCount)
5465 emitcode ("rrc", "a");
5469 /* rotate right accumulator */
5470 AccRol (8 - shCount);
5471 /* and kill the higher order bits */
5472 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5477 /*-----------------------------------------------------------------*/
5478 /* AccSRsh - signed right shift accumulator by known count */
5479 /*-----------------------------------------------------------------*/
5481 AccSRsh (int shCount)
5488 emitcode ("mov", "c,acc.7");
5489 emitcode ("rrc", "a");
5491 else if (shCount == 2)
5493 emitcode ("mov", "c,acc.7");
5494 emitcode ("rrc", "a");
5495 emitcode ("mov", "c,acc.7");
5496 emitcode ("rrc", "a");
5500 tlbl = newiTempLabel (NULL);
5501 /* rotate right accumulator */
5502 AccRol (8 - shCount);
5503 /* and kill the higher order bits */
5504 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5505 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5506 emitcode ("orl", "a,#0x%02x",
5507 (unsigned char) ~SRMask[shCount]);
5508 emitcode ("", "%05d$:", tlbl->key + 100);
5513 /*-----------------------------------------------------------------*/
5514 /* shiftR1Left2Result - shift right one byte from left to result */
5515 /*-----------------------------------------------------------------*/
5517 shiftR1Left2Result (operand * left, int offl,
5518 operand * result, int offr,
5519 int shCount, int sign)
5521 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5522 /* shift right accumulator */
5527 aopPut (AOP (result), "a", offr);
5530 /*-----------------------------------------------------------------*/
5531 /* shiftL1Left2Result - shift left one byte from left to result */
5532 /*-----------------------------------------------------------------*/
5534 shiftL1Left2Result (operand * left, int offl,
5535 operand * result, int offr, int shCount)
5538 l = aopGet (AOP (left), offl, FALSE, FALSE);
5540 /* shift left accumulator */
5542 aopPut (AOP (result), "a", offr);
5545 /*-----------------------------------------------------------------*/
5546 /* movLeft2Result - move byte from left to result */
5547 /*-----------------------------------------------------------------*/
5549 movLeft2Result (operand * left, int offl,
5550 operand * result, int offr, int sign)
5553 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5555 l = aopGet (AOP (left), offl, FALSE, FALSE);
5557 if (*l == '@' && (IS_AOP_PREG (result)))
5559 emitcode ("mov", "a,%s", l);
5560 aopPut (AOP (result), "a", offr);
5565 aopPut (AOP (result), l, offr);
5568 /* MSB sign in acc.7 ! */
5569 if (getDataSize (left) == offl + 1)
5571 emitcode ("mov", "a,%s", l);
5572 aopPut (AOP (result), "a", offr);
5579 /*-----------------------------------------------------------------*/
5580 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5581 /*-----------------------------------------------------------------*/
5585 emitcode ("rrc", "a");
5586 emitcode ("xch", "a,%s", x);
5587 emitcode ("rrc", "a");
5588 emitcode ("xch", "a,%s", x);
5591 /*-----------------------------------------------------------------*/
5592 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5593 /*-----------------------------------------------------------------*/
5597 emitcode ("xch", "a,%s", x);
5598 emitcode ("rlc", "a");
5599 emitcode ("xch", "a,%s", x);
5600 emitcode ("rlc", "a");
5603 /*-----------------------------------------------------------------*/
5604 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5605 /*-----------------------------------------------------------------*/
5609 emitcode ("xch", "a,%s", x);
5610 emitcode ("add", "a,acc");
5611 emitcode ("xch", "a,%s", x);
5612 emitcode ("rlc", "a");
5615 /*-----------------------------------------------------------------*/
5616 /* AccAXLsh - left shift a:x by known count (0..7) */
5617 /*-----------------------------------------------------------------*/
5619 AccAXLsh (char *x, int shCount)
5634 case 5: // AAAAABBB:CCCCCDDD
5636 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5638 emitcode ("anl", "a,#0x%02x",
5639 SLMask[shCount]); // BBB00000:CCCCCDDD
5641 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5643 AccRol (shCount); // DDDCCCCC:BBB00000
5645 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5647 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5649 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5651 emitcode ("anl", "a,#0x%02x",
5652 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5654 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5656 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5659 case 6: // AAAAAABB:CCCCCCDD
5660 emitcode ("anl", "a,#0x%02x",
5661 SRMask[shCount]); // 000000BB:CCCCCCDD
5662 emitcode ("mov", "c,acc.0"); // c = B
5663 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5665 AccAXRrl1 (x); // BCCCCCCD:D000000B
5666 AccAXRrl1 (x); // BBCCCCCC:DD000000
5668 emitcode("rrc","a");
5669 emitcode("xch","a,%s", x);
5670 emitcode("rrc","a");
5671 emitcode("mov","c,acc.0"); //<< get correct bit
5672 emitcode("xch","a,%s", x);
5674 emitcode("rrc","a");
5675 emitcode("xch","a,%s", x);
5676 emitcode("rrc","a");
5677 emitcode("xch","a,%s", x);
5680 case 7: // a:x <<= 7
5682 emitcode ("anl", "a,#0x%02x",
5683 SRMask[shCount]); // 0000000B:CCCCCCCD
5685 emitcode ("mov", "c,acc.0"); // c = B
5687 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5689 AccAXRrl1 (x); // BCCCCCCC:D0000000
5697 /*-----------------------------------------------------------------*/
5698 /* AccAXRsh - right shift a:x known count (0..7) */
5699 /*-----------------------------------------------------------------*/
5701 AccAXRsh (char *x, int shCount)
5709 AccAXRrl1 (x); // 0->a:x
5714 AccAXRrl1 (x); // 0->a:x
5717 AccAXRrl1 (x); // 0->a:x
5722 case 5: // AAAAABBB:CCCCCDDD = a:x
5724 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5726 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5728 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5730 emitcode ("anl", "a,#0x%02x",
5731 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5733 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5735 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5737 emitcode ("anl", "a,#0x%02x",
5738 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5740 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5742 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5744 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5747 case 6: // AABBBBBB:CCDDDDDD
5749 emitcode ("mov", "c,acc.7");
5750 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5752 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5754 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5756 emitcode ("anl", "a,#0x%02x",
5757 SRMask[shCount]); // 000000AA:BBBBBBCC
5760 case 7: // ABBBBBBB:CDDDDDDD
5762 emitcode ("mov", "c,acc.7"); // c = A
5764 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5766 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5768 emitcode ("anl", "a,#0x%02x",
5769 SRMask[shCount]); // 0000000A:BBBBBBBC
5777 /*-----------------------------------------------------------------*/
5778 /* AccAXRshS - right shift signed a:x known count (0..7) */
5779 /*-----------------------------------------------------------------*/
5781 AccAXRshS (char *x, int shCount)
5789 emitcode ("mov", "c,acc.7");
5790 AccAXRrl1 (x); // s->a:x
5794 emitcode ("mov", "c,acc.7");
5795 AccAXRrl1 (x); // s->a:x
5797 emitcode ("mov", "c,acc.7");
5798 AccAXRrl1 (x); // s->a:x
5803 case 5: // AAAAABBB:CCCCCDDD = a:x
5805 tlbl = newiTempLabel (NULL);
5806 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5808 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5810 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5812 emitcode ("anl", "a,#0x%02x",
5813 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5815 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5817 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5819 emitcode ("anl", "a,#0x%02x",
5820 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5822 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5824 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5826 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5828 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5829 emitcode ("orl", "a,#0x%02x",
5830 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5832 emitcode ("", "%05d$:", tlbl->key + 100);
5833 break; // SSSSAAAA:BBBCCCCC
5835 case 6: // AABBBBBB:CCDDDDDD
5837 tlbl = newiTempLabel (NULL);
5838 emitcode ("mov", "c,acc.7");
5839 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5841 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5843 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5845 emitcode ("anl", "a,#0x%02x",
5846 SRMask[shCount]); // 000000AA:BBBBBBCC
5848 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5849 emitcode ("orl", "a,#0x%02x",
5850 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5852 emitcode ("", "%05d$:", tlbl->key + 100);
5854 case 7: // ABBBBBBB:CDDDDDDD
5856 tlbl = newiTempLabel (NULL);
5857 emitcode ("mov", "c,acc.7"); // c = A
5859 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5861 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5863 emitcode ("anl", "a,#0x%02x",
5864 SRMask[shCount]); // 0000000A:BBBBBBBC
5866 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5867 emitcode ("orl", "a,#0x%02x",
5868 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5870 emitcode ("", "%05d$:", tlbl->key + 100);
5877 /*-----------------------------------------------------------------*/
5878 /* shiftL2Left2Result - shift left two bytes from left to result */
5879 /*-----------------------------------------------------------------*/
5881 shiftL2Left2Result (operand * left, int offl,
5882 operand * result, int offr, int shCount)
5884 if (sameRegs (AOP (result), AOP (left)) &&
5885 ((offl + MSB16) == offr))
5887 /* don't crash result[offr] */
5888 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5889 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5893 movLeft2Result (left, offl, result, offr, 0);
5894 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5896 /* ax << shCount (x = lsb(result)) */
5897 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5898 aopPut (AOP (result), "a", offr + MSB16);
5902 /*-----------------------------------------------------------------*/
5903 /* shiftR2Left2Result - shift right two bytes from left to result */
5904 /*-----------------------------------------------------------------*/
5906 shiftR2Left2Result (operand * left, int offl,
5907 operand * result, int offr,
5908 int shCount, int sign)
5910 if (sameRegs (AOP (result), AOP (left)) &&
5911 ((offl + MSB16) == offr))
5913 /* don't crash result[offr] */
5914 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5915 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5919 movLeft2Result (left, offl, result, offr, 0);
5920 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5922 /* a:x >> shCount (x = lsb(result)) */
5924 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5926 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5927 if (getDataSize (result) > 1)
5928 aopPut (AOP (result), "a", offr + MSB16);
5931 /*-----------------------------------------------------------------*/
5932 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5933 /*-----------------------------------------------------------------*/
5935 shiftLLeftOrResult (operand * left, int offl,
5936 operand * result, int offr, int shCount)
5938 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5939 /* shift left accumulator */
5941 /* or with result */
5942 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5943 /* back to result */
5944 aopPut (AOP (result), "a", offr);
5947 /*-----------------------------------------------------------------*/
5948 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5949 /*-----------------------------------------------------------------*/
5951 shiftRLeftOrResult (operand * left, int offl,
5952 operand * result, int offr, int shCount)
5954 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5955 /* shift right accumulator */
5957 /* or with result */
5958 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5959 /* back to result */
5960 aopPut (AOP (result), "a", offr);
5963 /*-----------------------------------------------------------------*/
5964 /* genlshOne - left shift a one byte quantity by known count */
5965 /*-----------------------------------------------------------------*/
5967 genlshOne (operand * result, operand * left, int shCount)
5969 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5972 /*-----------------------------------------------------------------*/
5973 /* genlshTwo - left shift two bytes by known amount != 0 */
5974 /*-----------------------------------------------------------------*/
5976 genlshTwo (operand * result, operand * left, int shCount)
5980 size = getDataSize (result);
5982 /* if shCount >= 8 */
5990 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5992 movLeft2Result (left, LSB, result, MSB16, 0);
5994 aopPut (AOP (result), zero, LSB);
5997 /* 1 <= shCount <= 7 */
6001 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6003 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6007 /*-----------------------------------------------------------------*/
6008 /* shiftLLong - shift left one long from left to result */
6009 /* offl = LSB or MSB16 */
6010 /*-----------------------------------------------------------------*/
6012 shiftLLong (operand * left, operand * result, int offr)
6015 int size = AOP_SIZE (result);
6017 if (size >= LSB + offr)
6019 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6021 emitcode ("add", "a,acc");
6022 if (sameRegs (AOP (left), AOP (result)) &&
6023 size >= MSB16 + offr && offr != LSB)
6024 emitcode ("xch", "a,%s",
6025 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6027 aopPut (AOP (result), "a", LSB + offr);
6030 if (size >= MSB16 + offr)
6032 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6034 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6037 emitcode ("rlc", "a");
6038 if (sameRegs (AOP (left), AOP (result)) &&
6039 size >= MSB24 + offr && offr != LSB)
6040 emitcode ("xch", "a,%s",
6041 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6043 aopPut (AOP (result), "a", MSB16 + offr);
6046 if (size >= MSB24 + offr)
6048 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6050 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6053 emitcode ("rlc", "a");
6054 if (sameRegs (AOP (left), AOP (result)) &&
6055 size >= MSB32 + offr && offr != LSB)
6056 emitcode ("xch", "a,%s",
6057 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6059 aopPut (AOP (result), "a", MSB24 + offr);
6062 if (size > MSB32 + offr)
6064 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6066 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6069 emitcode ("rlc", "a");
6070 aopPut (AOP (result), "a", MSB32 + offr);
6073 aopPut (AOP (result), zero, LSB);
6076 /*-----------------------------------------------------------------*/
6077 /* genlshFour - shift four byte by a known amount != 0 */
6078 /*-----------------------------------------------------------------*/
6080 genlshFour (operand * result, operand * left, int shCount)
6084 size = AOP_SIZE (result);
6086 /* if shifting more that 3 bytes */
6091 /* lowest order of left goes to the highest
6092 order of the destination */
6093 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6095 movLeft2Result (left, LSB, result, MSB32, 0);
6096 aopPut (AOP (result), zero, LSB);
6097 aopPut (AOP (result), zero, MSB16);
6098 aopPut (AOP (result), zero, MSB24);
6102 /* more than two bytes */
6103 else if (shCount >= 16)
6105 /* lower order two bytes goes to higher order two bytes */
6107 /* if some more remaining */
6109 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6112 movLeft2Result (left, MSB16, result, MSB32, 0);
6113 movLeft2Result (left, LSB, result, MSB24, 0);
6115 aopPut (AOP (result), zero, MSB16);
6116 aopPut (AOP (result), zero, LSB);
6120 /* if more than 1 byte */
6121 else if (shCount >= 8)
6123 /* lower order three bytes goes to higher order three bytes */
6128 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6130 movLeft2Result (left, LSB, result, MSB16, 0);
6136 movLeft2Result (left, MSB24, result, MSB32, 0);
6137 movLeft2Result (left, MSB16, result, MSB24, 0);
6138 movLeft2Result (left, LSB, result, MSB16, 0);
6139 aopPut (AOP (result), zero, LSB);
6141 else if (shCount == 1)
6142 shiftLLong (left, result, MSB16);
6145 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6146 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6147 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6148 aopPut (AOP (result), zero, LSB);
6153 /* 1 <= shCount <= 7 */
6154 else if (shCount <= 2)
6156 shiftLLong (left, result, LSB);
6158 shiftLLong (result, result, LSB);
6160 /* 3 <= shCount <= 7, optimize */
6163 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6164 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6165 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6169 /*-----------------------------------------------------------------*/
6170 /* genLeftShiftLiteral - left shifting by known count */
6171 /*-----------------------------------------------------------------*/
6173 genLeftShiftLiteral (operand * left,
6178 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6181 freeAsmop (right, NULL, ic, TRUE);
6183 aopOp (left, ic, FALSE);
6184 aopOp (result, ic, FALSE);
6186 size = getSize (operandType (result));
6189 emitcode ("; shift left ", "result %d, left %d", size,
6193 /* I suppose that the left size >= result size */
6198 movLeft2Result (left, size, result, size, 0);
6202 else if (shCount >= (size * 8))
6204 aopPut (AOP (result), zero, size);
6210 genlshOne (result, left, shCount);
6214 genlshTwo (result, left, shCount);
6218 genlshFour (result, left, shCount);
6221 fprintf(stderr, "*** ack! mystery literal shift!\n");
6225 freeAsmop (left, NULL, ic, TRUE);
6226 freeAsmop (result, NULL, ic, TRUE);
6229 /*-----------------------------------------------------------------*/
6230 /* genLeftShift - generates code for left shifting */
6231 /*-----------------------------------------------------------------*/
6233 genLeftShift (iCode * ic)
6235 operand *left, *right, *result;
6238 symbol *tlbl, *tlbl1;
6240 right = IC_RIGHT (ic);
6241 left = IC_LEFT (ic);
6242 result = IC_RESULT (ic);
6244 aopOp (right, ic, FALSE);
6246 /* if the shift count is known then do it
6247 as efficiently as possible */
6248 if (AOP_TYPE (right) == AOP_LIT)
6250 genLeftShiftLiteral (left, right, result, ic);
6254 /* shift count is unknown then we have to form
6255 a loop get the loop count in B : Note: we take
6256 only the lower order byte since shifting
6257 more that 32 bits make no sense anyway, ( the
6258 largest size of an object can be only 32 bits ) */
6260 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6261 emitcode ("inc", "b");
6262 freeAsmop (right, NULL, ic, TRUE);
6263 aopOp (left, ic, FALSE);
6264 aopOp (result, ic, FALSE);
6266 /* now move the left to the result if they are not the
6268 if (!sameRegs (AOP (left), AOP (result)) &&
6269 AOP_SIZE (result) > 1)
6272 size = AOP_SIZE (result);
6276 l = aopGet (AOP (left), offset, FALSE, TRUE);
6277 if (*l == '@' && (IS_AOP_PREG (result)))
6280 emitcode ("mov", "a,%s", l);
6281 aopPut (AOP (result), "a", offset);
6284 aopPut (AOP (result), l, offset);
6289 tlbl = newiTempLabel (NULL);
6290 size = AOP_SIZE (result);
6292 tlbl1 = newiTempLabel (NULL);
6294 /* if it is only one byte then */
6297 symbol *tlbl1 = newiTempLabel (NULL);
6299 l = aopGet (AOP (left), 0, FALSE, FALSE);
6301 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6302 emitcode ("", "%05d$:", tlbl->key + 100);
6303 emitcode ("add", "a,acc");
6304 emitcode ("", "%05d$:", tlbl1->key + 100);
6305 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6306 aopPut (AOP (result), "a", 0);
6310 reAdjustPreg (AOP (result));
6312 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6313 emitcode ("", "%05d$:", tlbl->key + 100);
6314 l = aopGet (AOP (result), offset, FALSE, FALSE);
6316 emitcode ("add", "a,acc");
6317 aopPut (AOP (result), "a", offset++);
6320 l = aopGet (AOP (result), offset, FALSE, FALSE);
6322 emitcode ("rlc", "a");
6323 aopPut (AOP (result), "a", offset++);
6325 reAdjustPreg (AOP (result));
6327 emitcode ("", "%05d$:", tlbl1->key + 100);
6328 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6330 freeAsmop (left, NULL, ic, TRUE);
6331 freeAsmop (result, NULL, ic, TRUE);
6334 /*-----------------------------------------------------------------*/
6335 /* genrshOne - right shift a one byte quantity by known count */
6336 /*-----------------------------------------------------------------*/
6338 genrshOne (operand * result, operand * left,
6339 int shCount, int sign)
6341 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6344 /*-----------------------------------------------------------------*/
6345 /* genrshTwo - right shift two bytes by known amount != 0 */
6346 /*-----------------------------------------------------------------*/
6348 genrshTwo (operand * result, operand * left,
6349 int shCount, int sign)
6351 /* if shCount >= 8 */
6356 shiftR1Left2Result (left, MSB16, result, LSB,
6359 movLeft2Result (left, MSB16, result, LSB, sign);
6360 addSign (result, MSB16, sign);
6363 /* 1 <= shCount <= 7 */
6365 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6368 /*-----------------------------------------------------------------*/
6369 /* shiftRLong - shift right one long from left to result */
6370 /* offl = LSB or MSB16 */
6371 /*-----------------------------------------------------------------*/
6373 shiftRLong (operand * left, int offl,
6374 operand * result, int sign)
6376 int isSameRegs=sameRegs(AOP(left),AOP(result));
6378 if (isSameRegs && offl>1) {
6379 // we are in big trouble, but this shouldn't happen
6380 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6383 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6388 emitcode ("rlc", "a");
6389 emitcode ("subb", "a,acc");
6390 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6392 aopPut (AOP(result), zero, MSB32);
6397 emitcode ("clr", "c");
6399 emitcode ("mov", "c,acc.7");
6402 emitcode ("rrc", "a");
6404 if (isSameRegs && offl==MSB16) {
6405 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6407 aopPut (AOP (result), "a", MSB32);
6408 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6411 emitcode ("rrc", "a");
6412 if (isSameRegs && offl==1) {
6413 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6415 aopPut (AOP (result), "a", MSB24);
6416 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6418 emitcode ("rrc", "a");
6419 aopPut (AOP (result), "a", MSB16 - offl);
6423 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6424 emitcode ("rrc", "a");
6425 aopPut (AOP (result), "a", LSB);
6429 /*-----------------------------------------------------------------*/
6430 /* genrshFour - shift four byte by a known amount != 0 */
6431 /*-----------------------------------------------------------------*/
6433 genrshFour (operand * result, operand * left,
6434 int shCount, int sign)
6436 /* if shifting more that 3 bytes */
6441 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6443 movLeft2Result (left, MSB32, result, LSB, sign);
6444 addSign (result, MSB16, sign);
6446 else if (shCount >= 16)
6450 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6453 movLeft2Result (left, MSB24, result, LSB, 0);
6454 movLeft2Result (left, MSB32, result, MSB16, sign);
6456 addSign (result, MSB24, sign);
6458 else if (shCount >= 8)
6462 shiftRLong (left, MSB16, result, sign);
6463 else if (shCount == 0)
6465 movLeft2Result (left, MSB16, result, LSB, 0);
6466 movLeft2Result (left, MSB24, result, MSB16, 0);
6467 movLeft2Result (left, MSB32, result, MSB24, sign);
6468 addSign (result, MSB32, sign);
6472 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6473 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6474 /* the last shift is signed */
6475 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6476 addSign (result, MSB32, sign);
6480 { /* 1 <= shCount <= 7 */
6483 shiftRLong (left, LSB, result, sign);
6485 shiftRLong (result, LSB, result, sign);
6489 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6490 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6491 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6496 /*-----------------------------------------------------------------*/
6497 /* genRightShiftLiteral - right shifting by known count */
6498 /*-----------------------------------------------------------------*/
6500 genRightShiftLiteral (operand * left,
6506 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6509 freeAsmop (right, NULL, ic, TRUE);
6511 aopOp (left, ic, FALSE);
6512 aopOp (result, ic, FALSE);
6515 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6519 size = getDataSize (left);
6520 /* test the LEFT size !!! */
6522 /* I suppose that the left size >= result size */
6525 size = getDataSize (result);
6527 movLeft2Result (left, size, result, size, 0);
6530 else if (shCount >= (size * 8))
6533 /* get sign in acc.7 */
6534 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6535 addSign (result, LSB, sign);
6542 genrshOne (result, left, shCount, sign);
6546 genrshTwo (result, left, shCount, sign);
6550 genrshFour (result, left, shCount, sign);
6556 freeAsmop (left, NULL, ic, TRUE);
6557 freeAsmop (result, NULL, ic, TRUE);
6561 /*-----------------------------------------------------------------*/
6562 /* genSignedRightShift - right shift of signed number */
6563 /*-----------------------------------------------------------------*/
6565 genSignedRightShift (iCode * ic)
6567 operand *right, *left, *result;
6570 symbol *tlbl, *tlbl1;
6572 /* we do it the hard way put the shift count in b
6573 and loop thru preserving the sign */
6575 right = IC_RIGHT (ic);
6576 left = IC_LEFT (ic);
6577 result = IC_RESULT (ic);
6579 aopOp (right, ic, FALSE);
6582 if (AOP_TYPE (right) == AOP_LIT)
6584 genRightShiftLiteral (left, right, result, ic, 1);
6587 /* shift count is unknown then we have to form
6588 a loop get the loop count in B : Note: we take
6589 only the lower order byte since shifting
6590 more that 32 bits make no sense anyway, ( the
6591 largest size of an object can be only 32 bits ) */
6593 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6594 emitcode ("inc", "b");
6595 freeAsmop (right, NULL, ic, TRUE);
6596 aopOp (left, ic, FALSE);
6597 aopOp (result, ic, FALSE);
6599 /* now move the left to the result if they are not the
6601 if (!sameRegs (AOP (left), AOP (result)) &&
6602 AOP_SIZE (result) > 1)
6605 size = AOP_SIZE (result);
6609 l = aopGet (AOP (left), offset, FALSE, TRUE);
6610 if (*l == '@' && IS_AOP_PREG (result))
6613 emitcode ("mov", "a,%s", l);
6614 aopPut (AOP (result), "a", offset);
6617 aopPut (AOP (result), l, offset);
6622 /* mov the highest order bit to OVR */
6623 tlbl = newiTempLabel (NULL);
6624 tlbl1 = newiTempLabel (NULL);
6626 size = AOP_SIZE (result);
6628 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6629 emitcode ("rlc", "a");
6630 emitcode ("mov", "ov,c");
6631 /* if it is only one byte then */
6634 l = aopGet (AOP (left), 0, FALSE, FALSE);
6636 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6637 emitcode ("", "%05d$:", tlbl->key + 100);
6638 emitcode ("mov", "c,ov");
6639 emitcode ("rrc", "a");
6640 emitcode ("", "%05d$:", tlbl1->key + 100);
6641 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6642 aopPut (AOP (result), "a", 0);
6646 reAdjustPreg (AOP (result));
6647 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6648 emitcode ("", "%05d$:", tlbl->key + 100);
6649 emitcode ("mov", "c,ov");
6652 l = aopGet (AOP (result), offset, FALSE, FALSE);
6654 emitcode ("rrc", "a");
6655 aopPut (AOP (result), "a", offset--);
6657 reAdjustPreg (AOP (result));
6658 emitcode ("", "%05d$:", tlbl1->key + 100);
6659 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6662 freeAsmop (left, NULL, ic, TRUE);
6663 freeAsmop (result, NULL, ic, TRUE);
6666 /*-----------------------------------------------------------------*/
6667 /* genRightShift - generate code for right shifting */
6668 /*-----------------------------------------------------------------*/
6670 genRightShift (iCode * ic)
6672 operand *right, *left, *result;
6676 symbol *tlbl, *tlbl1;
6678 /* if signed then we do it the hard way preserve the
6679 sign bit moving it inwards */
6680 retype = getSpec (operandType (IC_RESULT (ic)));
6682 if (!SPEC_USIGN (retype))
6684 genSignedRightShift (ic);
6688 /* signed & unsigned types are treated the same : i.e. the
6689 signed is NOT propagated inwards : quoting from the
6690 ANSI - standard : "for E1 >> E2, is equivalent to division
6691 by 2**E2 if unsigned or if it has a non-negative value,
6692 otherwise the result is implementation defined ", MY definition
6693 is that the sign does not get propagated */
6695 right = IC_RIGHT (ic);
6696 left = IC_LEFT (ic);
6697 result = IC_RESULT (ic);
6699 aopOp (right, ic, FALSE);
6701 /* if the shift count is known then do it
6702 as efficiently as possible */
6703 if (AOP_TYPE (right) == AOP_LIT)
6705 genRightShiftLiteral (left, right, result, ic, 0);
6709 /* shift count is unknown then we have to form
6710 a loop get the loop count in B : Note: we take
6711 only the lower order byte since shifting
6712 more that 32 bits make no sense anyway, ( the
6713 largest size of an object can be only 32 bits ) */
6715 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6716 emitcode ("inc", "b");
6717 freeAsmop (right, NULL, ic, TRUE);
6718 aopOp (left, ic, FALSE);
6719 aopOp (result, ic, FALSE);
6721 /* now move the left to the result if they are not the
6723 if (!sameRegs (AOP (left), AOP (result)) &&
6724 AOP_SIZE (result) > 1)
6727 size = AOP_SIZE (result);
6731 l = aopGet (AOP (left), offset, FALSE, TRUE);
6732 if (*l == '@' && IS_AOP_PREG (result))
6735 emitcode ("mov", "a,%s", l);
6736 aopPut (AOP (result), "a", offset);
6739 aopPut (AOP (result), l, offset);
6744 tlbl = newiTempLabel (NULL);
6745 tlbl1 = newiTempLabel (NULL);
6746 size = AOP_SIZE (result);
6749 /* if it is only one byte then */
6752 l = aopGet (AOP (left), 0, FALSE, FALSE);
6754 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6755 emitcode ("", "%05d$:", tlbl->key + 100);
6757 emitcode ("rrc", "a");
6758 emitcode ("", "%05d$:", tlbl1->key + 100);
6759 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6760 aopPut (AOP (result), "a", 0);
6764 reAdjustPreg (AOP (result));
6765 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6766 emitcode ("", "%05d$:", tlbl->key + 100);
6770 l = aopGet (AOP (result), offset, FALSE, FALSE);
6772 emitcode ("rrc", "a");
6773 aopPut (AOP (result), "a", offset--);
6775 reAdjustPreg (AOP (result));
6777 emitcode ("", "%05d$:", tlbl1->key + 100);
6778 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6781 freeAsmop (left, NULL, ic, TRUE);
6782 freeAsmop (result, NULL, ic, TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genUnpackBits - generates code for unpacking bits */
6787 /*-----------------------------------------------------------------*/
6789 genUnpackBits (operand * result, char *rname, int ptype)
6797 etype = getSpec (operandType (result));
6798 rsize = getSize (operandType (result));
6799 /* read the first byte */
6805 emitcode ("mov", "a,@%s", rname);
6809 emitcode ("movx", "a,@%s", rname);
6813 emitcode ("movx", "a,@dptr");
6817 emitcode ("clr", "a");
6818 emitcode ("movc", "a,@a+dptr");
6822 emitcode ("lcall", "__gptrget");
6826 rlen = SPEC_BLEN (etype);
6828 /* if we have bitdisplacement then it fits */
6829 /* into this byte completely or if length is */
6830 /* less than a byte */
6831 if ((shCnt = SPEC_BSTR (etype)) ||
6832 (SPEC_BLEN (etype) <= 8))
6835 /* shift right acc */
6838 emitcode ("anl", "a,#0x%02x",
6839 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6840 aopPut (AOP (result), "a", offset++);
6844 /* bit field did not fit in a byte */
6845 aopPut (AOP (result), "a", offset++);
6854 emitcode ("inc", "%s", rname);
6855 emitcode ("mov", "a,@%s", rname);
6859 emitcode ("inc", "%s", rname);
6860 emitcode ("movx", "a,@%s", rname);
6864 emitcode ("inc", "dptr");
6865 emitcode ("movx", "a,@dptr");
6869 emitcode ("clr", "a");
6870 emitcode ("inc", "dptr");
6871 emitcode ("movc", "a,@a+dptr");
6875 emitcode ("inc", "dptr");
6876 emitcode ("lcall", "__gptrget");
6881 /* if we are done */
6885 aopPut (AOP (result), "a", offset++);
6891 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6893 aopPut (AOP (result), "a", offset++);
6901 aopPut (AOP (result), zero, offset++);
6907 /*-----------------------------------------------------------------*/
6908 /* genDataPointerGet - generates code when ptr offset is known */
6909 /*-----------------------------------------------------------------*/
6911 genDataPointerGet (operand * left,
6917 int size, offset = 0;
6918 aopOp (result, ic, TRUE);
6920 /* get the string representation of the name */
6921 l = aopGet (AOP (left), 0, FALSE, TRUE);
6922 size = AOP_SIZE (result);
6926 sprintf (buffer, "(%s + %d)", l + 1, offset);
6928 sprintf (buffer, "%s", l + 1);
6929 aopPut (AOP (result), buffer, offset++);
6932 freeAsmop (left, NULL, ic, TRUE);
6933 freeAsmop (result, NULL, ic, TRUE);
6936 /*-----------------------------------------------------------------*/
6937 /* genNearPointerGet - emitcode for near pointer fetch */
6938 /*-----------------------------------------------------------------*/
6940 genNearPointerGet (operand * left,
6948 sym_link *rtype, *retype;
6949 sym_link *ltype = operandType (left);
6952 rtype = operandType (result);
6953 retype = getSpec (rtype);
6955 aopOp (left, ic, FALSE);
6957 /* if left is rematerialisable and
6958 result is not bit variable type and
6959 the left is pointer to data space i.e
6960 lower 128 bytes of space */
6961 if (AOP_TYPE (left) == AOP_IMMD &&
6962 !IS_BITVAR (retype) &&
6963 DCL_TYPE (ltype) == POINTER)
6965 genDataPointerGet (left, result, ic);
6969 /* if the value is already in a pointer register
6970 then don't need anything more */
6971 if (!AOP_INPREG (AOP (left)))
6973 /* otherwise get a free pointer register */
6975 preg = getFreePtr (ic, &aop, FALSE);
6976 emitcode ("mov", "%s,%s",
6978 aopGet (AOP (left), 0, FALSE, TRUE));
6982 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6984 //aopOp (result, ic, FALSE);
6985 aopOp (result, ic, result?TRUE:FALSE);
6987 /* if bitfield then unpack the bits */
6988 if (IS_BITVAR (retype))
6989 genUnpackBits (result, rname, POINTER);
6992 /* we have can just get the values */
6993 int size = AOP_SIZE (result);
6998 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7001 emitcode ("mov", "a,@%s", rname);
7002 aopPut (AOP (result), "a", offset);
7006 sprintf (buffer, "@%s", rname);
7007 aopPut (AOP (result), buffer, offset);
7011 emitcode ("inc", "%s", rname);
7015 /* now some housekeeping stuff */
7016 if (aop) /* we had to allocate for this iCode */
7018 if (pi) { /* post increment present */
7019 aopPut(AOP ( left ),rname,0);
7021 freeAsmop (NULL, aop, ic, TRUE);
7025 /* we did not allocate which means left
7026 already in a pointer register, then
7027 if size > 0 && this could be used again
7028 we have to point it back to where it
7030 if ((AOP_SIZE (result) > 1 &&
7031 !OP_SYMBOL (left)->remat &&
7032 (OP_SYMBOL (left)->liveTo > ic->seq ||
7036 int size = AOP_SIZE (result) - 1;
7038 emitcode ("dec", "%s", rname);
7043 freeAsmop (left, NULL, ic, TRUE);
7044 freeAsmop (result, NULL, ic, TRUE);
7045 if (pi) pi->generated = 1;
7048 /*-----------------------------------------------------------------*/
7049 /* genPagedPointerGet - emitcode for paged pointer fetch */
7050 /*-----------------------------------------------------------------*/
7052 genPagedPointerGet (operand * left,
7060 sym_link *rtype, *retype;
7062 rtype = operandType (result);
7063 retype = getSpec (rtype);
7065 aopOp (left, ic, FALSE);
7067 /* if the value is already in a pointer register
7068 then don't need anything more */
7069 if (!AOP_INPREG (AOP (left)))
7071 /* otherwise get a free pointer register */
7073 preg = getFreePtr (ic, &aop, FALSE);
7074 emitcode ("mov", "%s,%s",
7076 aopGet (AOP (left), 0, FALSE, TRUE));
7080 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7082 aopOp (result, ic, FALSE);
7084 /* if bitfield then unpack the bits */
7085 if (IS_BITVAR (retype))
7086 genUnpackBits (result, rname, PPOINTER);
7089 /* we have can just get the values */
7090 int size = AOP_SIZE (result);
7096 emitcode ("movx", "a,@%s", rname);
7097 aopPut (AOP (result), "a", offset);
7102 emitcode ("inc", "%s", rname);
7106 /* now some housekeeping stuff */
7107 if (aop) /* we had to allocate for this iCode */
7109 if (pi) aopPut ( AOP (left), rname, 0);
7110 freeAsmop (NULL, aop, ic, TRUE);
7114 /* we did not allocate which means left
7115 already in a pointer register, then
7116 if size > 0 && this could be used again
7117 we have to point it back to where it
7119 if ((AOP_SIZE (result) > 1 &&
7120 !OP_SYMBOL (left)->remat &&
7121 (OP_SYMBOL (left)->liveTo > ic->seq ||
7125 int size = AOP_SIZE (result) - 1;
7127 emitcode ("dec", "%s", rname);
7132 freeAsmop (left, NULL, ic, TRUE);
7133 freeAsmop (result, NULL, ic, TRUE);
7134 if (pi) pi->generated = 1;
7138 /*-----------------------------------------------------------------*/
7139 /* genFarPointerGet - gget value from far space */
7140 /*-----------------------------------------------------------------*/
7142 genFarPointerGet (operand * left,
7143 operand * result, iCode * ic, iCode * pi)
7146 sym_link *retype = getSpec (operandType (result));
7148 aopOp (left, ic, FALSE);
7150 /* if the operand is already in dptr
7151 then we do nothing else we move the value to dptr */
7152 if (AOP_TYPE (left) != AOP_STR)
7154 /* if this is remateriazable */
7155 if (AOP_TYPE (left) == AOP_IMMD)
7156 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7158 { /* we need to get it byte by byte */
7159 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7160 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7163 /* so dptr know contains the address */
7164 aopOp (result, ic, FALSE);
7166 /* if bit then unpack */
7167 if (IS_BITVAR (retype))
7168 genUnpackBits (result, "dptr", FPOINTER);
7171 size = AOP_SIZE (result);
7176 emitcode ("movx", "a,@dptr");
7177 aopPut (AOP (result), "a", offset++);
7179 emitcode ("inc", "dptr");
7183 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7184 aopPut ( AOP (left), "dpl", 0);
7185 aopPut ( AOP (left), "dph", 1);
7188 freeAsmop (left, NULL, ic, TRUE);
7189 freeAsmop (result, NULL, ic, TRUE);
7192 /*-----------------------------------------------------------------*/
7193 /* genCodePointerGet - gget value from code space */
7194 /*-----------------------------------------------------------------*/
7196 genCodePointerGet (operand * left,
7197 operand * result, iCode * ic, iCode *pi)
7200 sym_link *retype = getSpec (operandType (result));
7202 aopOp (left, ic, FALSE);
7204 /* if the operand is already in dptr
7205 then we do nothing else we move the value to dptr */
7206 if (AOP_TYPE (left) != AOP_STR)
7208 /* if this is remateriazable */
7209 if (AOP_TYPE (left) == AOP_IMMD)
7210 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7212 { /* we need to get it byte by byte */
7213 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7214 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7217 /* so dptr know contains the address */
7218 aopOp (result, ic, FALSE);
7220 /* if bit then unpack */
7221 if (IS_BITVAR (retype))
7222 genUnpackBits (result, "dptr", CPOINTER);
7225 size = AOP_SIZE (result);
7230 emitcode ("clr", "a");
7231 emitcode ("movc", "a,@a+dptr");
7232 aopPut (AOP (result), "a", offset++);
7234 emitcode ("inc", "dptr");
7238 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7239 aopPut ( AOP (left), "dpl", 0);
7240 aopPut ( AOP (left), "dph", 1);
7243 freeAsmop (left, NULL, ic, TRUE);
7244 freeAsmop (result, NULL, ic, TRUE);
7247 /*-----------------------------------------------------------------*/
7248 /* genGenPointerGet - gget value from generic pointer space */
7249 /*-----------------------------------------------------------------*/
7251 genGenPointerGet (operand * left,
7252 operand * result, iCode * ic, iCode *pi)
7255 sym_link *retype = getSpec (operandType (result));
7257 aopOp (left, ic, FALSE);
7259 /* if the operand is already in dptr
7260 then we do nothing else we move the value to dptr */
7261 if (AOP_TYPE (left) != AOP_STR)
7263 /* if this is remateriazable */
7264 if (AOP_TYPE (left) == AOP_IMMD)
7266 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7267 emitcode ("mov", "b,#%d", pointerCode (retype));
7270 { /* we need to get it byte by byte */
7271 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7272 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7273 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7276 /* so dptr know contains the address */
7277 aopOp (result, ic, FALSE);
7279 /* if bit then unpack */
7280 if (IS_BITVAR (retype))
7281 genUnpackBits (result, "dptr", GPOINTER);
7284 size = AOP_SIZE (result);
7289 emitcode ("lcall", "__gptrget");
7290 aopPut (AOP (result), "a", offset++);
7292 emitcode ("inc", "dptr");
7296 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7297 aopPut ( AOP (left), "dpl", 0);
7298 aopPut ( AOP (left), "dph", 1);
7301 freeAsmop (left, NULL, ic, TRUE);
7302 freeAsmop (result, NULL, ic, TRUE);
7305 /*-----------------------------------------------------------------*/
7306 /* genPointerGet - generate code for pointer get */
7307 /*-----------------------------------------------------------------*/
7309 genPointerGet (iCode * ic, iCode *pi)
7311 operand *left, *result;
7312 sym_link *type, *etype;
7315 left = IC_LEFT (ic);
7316 result = IC_RESULT (ic);
7318 /* depending on the type of pointer we need to
7319 move it to the correct pointer register */
7320 type = operandType (left);
7321 etype = getSpec (type);
7322 /* if left is of type of pointer then it is simple */
7323 if (IS_PTR (type) && !IS_FUNC (type->next))
7324 p_type = DCL_TYPE (type);
7327 /* we have to go by the storage class */
7328 p_type = PTR_TYPE (SPEC_OCLS (etype));
7331 /* now that we have the pointer type we assign
7332 the pointer values */
7338 genNearPointerGet (left, result, ic, pi);
7342 genPagedPointerGet (left, result, ic, pi);
7346 genFarPointerGet (left, result, ic, pi);
7350 genCodePointerGet (left, result, ic, pi);
7354 genGenPointerGet (left, result, ic, pi);
7360 /*-----------------------------------------------------------------*/
7361 /* genPackBits - generates code for packed bit storage */
7362 /*-----------------------------------------------------------------*/
7364 genPackBits (sym_link * etype,
7366 char *rname, int p_type)
7374 blen = SPEC_BLEN (etype);
7375 bstr = SPEC_BSTR (etype);
7377 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7380 /* if the bit lenth is less than or */
7381 /* it exactly fits a byte then */
7382 if (SPEC_BLEN (etype) <= 8)
7384 shCount = SPEC_BSTR (etype);
7386 /* shift left acc */
7389 if (SPEC_BLEN (etype) < 8)
7390 { /* if smaller than a byte */
7396 emitcode ("mov", "b,a");
7397 emitcode ("mov", "a,@%s", rname);
7401 emitcode ("mov", "b,a");
7402 emitcode ("movx", "a,@dptr");
7406 emitcode ("push", "b");
7407 emitcode ("push", "acc");
7408 emitcode ("lcall", "__gptrget");
7409 emitcode ("pop", "b");
7413 emitcode ("anl", "a,#0x%02x", (unsigned char)
7414 ((unsigned char) (0xFF << (blen + bstr)) |
7415 (unsigned char) (0xFF >> (8 - bstr))));
7416 emitcode ("orl", "a,b");
7417 if (p_type == GPOINTER)
7418 emitcode ("pop", "b");
7425 emitcode ("mov", "@%s,a", rname);
7429 emitcode ("movx", "@dptr,a");
7433 emitcode ("lcall", "__gptrput");
7438 if (SPEC_BLEN (etype) <= 8)
7441 emitcode ("inc", "%s", rname);
7442 rLen = SPEC_BLEN (etype);
7444 /* now generate for lengths greater than one byte */
7448 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7460 emitcode ("mov", "@%s,a", rname);
7463 emitcode ("mov", "@%s,%s", rname, l);
7468 emitcode ("movx", "@dptr,a");
7473 emitcode ("lcall", "__gptrput");
7476 emitcode ("inc", "%s", rname);
7481 /* last last was not complete */
7484 /* save the byte & read byte */
7488 emitcode ("mov", "b,a");
7489 emitcode ("mov", "a,@%s", rname);
7493 emitcode ("mov", "b,a");
7494 emitcode ("movx", "a,@dptr");
7498 emitcode ("push", "b");
7499 emitcode ("push", "acc");
7500 emitcode ("lcall", "__gptrget");
7501 emitcode ("pop", "b");
7505 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7506 emitcode ("orl", "a,b");
7509 if (p_type == GPOINTER)
7510 emitcode ("pop", "b");
7516 emitcode ("mov", "@%s,a", rname);
7520 emitcode ("movx", "@dptr,a");
7524 emitcode ("lcall", "__gptrput");
7528 /*-----------------------------------------------------------------*/
7529 /* genDataPointerSet - remat pointer to data space */
7530 /*-----------------------------------------------------------------*/
7532 genDataPointerSet (operand * right,
7536 int size, offset = 0;
7537 char *l, buffer[256];
7539 aopOp (right, ic, FALSE);
7541 l = aopGet (AOP (result), 0, FALSE, TRUE);
7542 size = AOP_SIZE (right);
7546 sprintf (buffer, "(%s + %d)", l + 1, offset);
7548 sprintf (buffer, "%s", l + 1);
7549 emitcode ("mov", "%s,%s", buffer,
7550 aopGet (AOP (right), offset++, FALSE, FALSE));
7553 freeAsmop (right, NULL, ic, TRUE);
7554 freeAsmop (result, NULL, ic, TRUE);
7557 /*-----------------------------------------------------------------*/
7558 /* genNearPointerSet - emitcode for near pointer put */
7559 /*-----------------------------------------------------------------*/
7561 genNearPointerSet (operand * right,
7569 sym_link *retype, *letype;
7570 sym_link *ptype = operandType (result);
7572 retype = getSpec (operandType (right));
7573 letype = getSpec (ptype);
7574 aopOp (result, ic, FALSE);
7576 /* if the result is rematerializable &
7577 in data space & not a bit variable */
7578 if (AOP_TYPE (result) == AOP_IMMD &&
7579 DCL_TYPE (ptype) == POINTER &&
7580 !IS_BITVAR (retype) &&
7581 !IS_BITVAR (letype))
7583 genDataPointerSet (right, result, ic);
7587 /* if the value is already in a pointer register
7588 then don't need anything more */
7589 if (!AOP_INPREG (AOP (result)))
7592 //AOP_TYPE (result) == AOP_STK
7596 // Aha, it is a pointer, just in disguise.
7597 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7600 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7601 __FILE__, __LINE__);
7606 rname++; // skip the '@'.
7611 /* otherwise get a free pointer register */
7613 preg = getFreePtr (ic, &aop, FALSE);
7614 emitcode ("mov", "%s,%s",
7616 aopGet (AOP (result), 0, FALSE, TRUE));
7622 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7625 aopOp (right, ic, FALSE);
7627 /* if bitfield then unpack the bits */
7628 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7629 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7632 /* we have can just get the values */
7633 int size = AOP_SIZE (right);
7638 l = aopGet (AOP (right), offset, FALSE, TRUE);
7642 emitcode ("mov", "@%s,a", rname);
7645 emitcode ("mov", "@%s,%s", rname, l);
7647 emitcode ("inc", "%s", rname);
7652 /* now some housekeeping stuff */
7653 if (aop) /* we had to allocate for this iCode */
7655 if (pi) aopPut (AOP (result),rname,0);
7656 freeAsmop (NULL, aop, ic, TRUE);
7660 /* we did not allocate which means left
7661 already in a pointer register, then
7662 if size > 0 && this could be used again
7663 we have to point it back to where it
7665 if ((AOP_SIZE (right) > 1 &&
7666 !OP_SYMBOL (result)->remat &&
7667 (OP_SYMBOL (result)->liveTo > ic->seq ||
7671 int size = AOP_SIZE (right) - 1;
7673 emitcode ("dec", "%s", rname);
7678 if (pi) pi->generated = 1;
7679 freeAsmop (result, NULL, ic, TRUE);
7680 freeAsmop (right, NULL, ic, TRUE);
7683 /*-----------------------------------------------------------------*/
7684 /* genPagedPointerSet - emitcode for Paged pointer put */
7685 /*-----------------------------------------------------------------*/
7687 genPagedPointerSet (operand * right,
7695 sym_link *retype, *letype;
7697 retype = getSpec (operandType (right));
7698 letype = getSpec (operandType (result));
7700 aopOp (result, ic, FALSE);
7702 /* if the value is already in a pointer register
7703 then don't need anything more */
7704 if (!AOP_INPREG (AOP (result)))
7706 /* otherwise get a free pointer register */
7708 preg = getFreePtr (ic, &aop, FALSE);
7709 emitcode ("mov", "%s,%s",
7711 aopGet (AOP (result), 0, FALSE, TRUE));
7715 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7717 aopOp (right, ic, FALSE);
7719 /* if bitfield then unpack the bits */
7720 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7721 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7724 /* we have can just get the values */
7725 int size = AOP_SIZE (right);
7730 l = aopGet (AOP (right), offset, FALSE, TRUE);
7733 emitcode ("movx", "@%s,a", rname);
7736 emitcode ("inc", "%s", rname);
7742 /* now some housekeeping stuff */
7743 if (aop) /* we had to allocate for this iCode */
7745 if (pi) aopPut (AOP (result),rname,0);
7746 freeAsmop (NULL, aop, ic, TRUE);
7750 /* we did not allocate which means left
7751 already in a pointer register, then
7752 if size > 0 && this could be used again
7753 we have to point it back to where it
7755 if (AOP_SIZE (right) > 1 &&
7756 !OP_SYMBOL (result)->remat &&
7757 (OP_SYMBOL (result)->liveTo > ic->seq ||
7760 int size = AOP_SIZE (right) - 1;
7762 emitcode ("dec", "%s", rname);
7767 if (pi) pi->generated = 1;
7768 freeAsmop (result, NULL, ic, TRUE);
7769 freeAsmop (right, NULL, ic, TRUE);
7774 /*-----------------------------------------------------------------*/
7775 /* genFarPointerSet - set value from far space */
7776 /*-----------------------------------------------------------------*/
7778 genFarPointerSet (operand * right,
7779 operand * result, iCode * ic, iCode * pi)
7782 sym_link *retype = getSpec (operandType (right));
7783 sym_link *letype = getSpec (operandType (result));
7784 aopOp (result, ic, FALSE);
7786 /* if the operand is already in dptr
7787 then we do nothing else we move the value to dptr */
7788 if (AOP_TYPE (result) != AOP_STR)
7790 /* if this is remateriazable */
7791 if (AOP_TYPE (result) == AOP_IMMD)
7792 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7794 { /* we need to get it byte by byte */
7795 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7796 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7799 /* so dptr know contains the address */
7800 aopOp (right, ic, FALSE);
7802 /* if bit then unpack */
7803 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7804 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7807 size = AOP_SIZE (right);
7812 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7814 emitcode ("movx", "@dptr,a");
7816 emitcode ("inc", "dptr");
7819 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7820 aopPut (AOP(result),"dpl",0);
7821 aopPut (AOP(result),"dph",1);
7824 freeAsmop (result, NULL, ic, TRUE);
7825 freeAsmop (right, NULL, ic, TRUE);
7828 /*-----------------------------------------------------------------*/
7829 /* genGenPointerSet - set value from generic pointer space */
7830 /*-----------------------------------------------------------------*/
7832 genGenPointerSet (operand * right,
7833 operand * result, iCode * ic, iCode * pi)
7836 sym_link *retype = getSpec (operandType (right));
7837 sym_link *letype = getSpec (operandType (result));
7839 aopOp (result, ic, FALSE);
7841 /* if the operand is already in dptr
7842 then we do nothing else we move the value to dptr */
7843 if (AOP_TYPE (result) != AOP_STR)
7845 /* if this is remateriazable */
7846 if (AOP_TYPE (result) == AOP_IMMD)
7848 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7849 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7852 { /* we need to get it byte by byte */
7853 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7854 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7855 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7858 /* so dptr know contains the address */
7859 aopOp (right, ic, FALSE);
7861 /* if bit then unpack */
7862 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7863 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7866 size = AOP_SIZE (right);
7871 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7873 emitcode ("lcall", "__gptrput");
7875 emitcode ("inc", "dptr");
7879 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7880 aopPut (AOP(result),"dpl",0);
7881 aopPut (AOP(result),"dph",1);
7884 freeAsmop (result, NULL, ic, TRUE);
7885 freeAsmop (right, NULL, ic, TRUE);
7888 /*-----------------------------------------------------------------*/
7889 /* genPointerSet - stores the value into a pointer location */
7890 /*-----------------------------------------------------------------*/
7892 genPointerSet (iCode * ic, iCode *pi)
7894 operand *right, *result;
7895 sym_link *type, *etype;
7898 right = IC_RIGHT (ic);
7899 result = IC_RESULT (ic);
7901 /* depending on the type of pointer we need to
7902 move it to the correct pointer register */
7903 type = operandType (result);
7904 etype = getSpec (type);
7905 /* if left is of type of pointer then it is simple */
7906 if (IS_PTR (type) && !IS_FUNC (type->next))
7908 p_type = DCL_TYPE (type);
7912 /* we have to go by the storage class */
7913 p_type = PTR_TYPE (SPEC_OCLS (etype));
7916 /* now that we have the pointer type we assign
7917 the pointer values */
7923 genNearPointerSet (right, result, ic, pi);
7927 genPagedPointerSet (right, result, ic, pi);
7931 genFarPointerSet (right, result, ic, pi);
7935 genGenPointerSet (right, result, ic, pi);
7941 /*-----------------------------------------------------------------*/
7942 /* genIfx - generate code for Ifx statement */
7943 /*-----------------------------------------------------------------*/
7945 genIfx (iCode * ic, iCode * popIc)
7947 operand *cond = IC_COND (ic);
7950 aopOp (cond, ic, FALSE);
7952 /* get the value into acc */
7953 if (AOP_TYPE (cond) != AOP_CRY)
7957 /* the result is now in the accumulator */
7958 freeAsmop (cond, NULL, ic, TRUE);
7960 /* if there was something to be popped then do it */
7964 /* if the condition is a bit variable */
7965 if (isbit && IS_ITEMP (cond) &&
7967 genIfxJump (ic, SPIL_LOC (cond)->rname);
7968 else if (isbit && !IS_ITEMP (cond))
7969 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7971 genIfxJump (ic, "a");
7976 /*-----------------------------------------------------------------*/
7977 /* genAddrOf - generates code for address of */
7978 /*-----------------------------------------------------------------*/
7980 genAddrOf (iCode * ic)
7982 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7985 aopOp (IC_RESULT (ic), ic, FALSE);
7987 /* if the operand is on the stack then we
7988 need to get the stack offset of this
7992 /* if it has an offset then we need to compute
7996 emitcode ("mov", "a,_bp");
7997 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7998 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8002 /* we can just move _bp */
8003 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8005 /* fill the result with zero */
8006 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8011 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8017 /* object not on stack then we need the name */
8018 size = AOP_SIZE (IC_RESULT (ic));
8023 char s[SDCC_NAME_MAX];
8025 sprintf (s, "#(%s >> %d)",
8029 sprintf (s, "#%s", sym->rname);
8030 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8034 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8038 /*-----------------------------------------------------------------*/
8039 /* genFarFarAssign - assignment when both are in far space */
8040 /*-----------------------------------------------------------------*/
8042 genFarFarAssign (operand * result, operand * right, iCode * ic)
8044 int size = AOP_SIZE (right);
8047 /* first push the right side on to the stack */
8050 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8052 emitcode ("push", "acc");
8055 freeAsmop (right, NULL, ic, FALSE);
8056 /* now assign DPTR to result */
8057 aopOp (result, ic, FALSE);
8058 size = AOP_SIZE (result);
8061 emitcode ("pop", "acc");
8062 aopPut (AOP (result), "a", --offset);
8064 freeAsmop (result, NULL, ic, FALSE);
8068 /*-----------------------------------------------------------------*/
8069 /* genAssign - generate code for assignment */
8070 /*-----------------------------------------------------------------*/
8072 genAssign (iCode * ic)
8074 operand *result, *right;
8076 unsigned long lit = 0L;
8078 D(emitcode(";","genAssign"));
8080 result = IC_RESULT (ic);
8081 right = IC_RIGHT (ic);
8083 /* if they are the same */
8084 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8087 aopOp (right, ic, FALSE);
8089 /* special case both in far space */
8090 if (AOP_TYPE (right) == AOP_DPTR &&
8091 IS_TRUE_SYMOP (result) &&
8092 isOperandInFarSpace (result))
8095 genFarFarAssign (result, right, ic);
8099 aopOp (result, ic, TRUE);
8101 /* if they are the same registers */
8102 if (sameRegs (AOP (right), AOP (result)))
8105 /* if the result is a bit */
8106 if (AOP_TYPE (result) == AOP_CRY)
8109 /* if the right size is a literal then
8110 we know what the value is */
8111 if (AOP_TYPE (right) == AOP_LIT)
8113 if (((int) operandLitValue (right)))
8114 aopPut (AOP (result), one, 0);
8116 aopPut (AOP (result), zero, 0);
8120 /* the right is also a bit variable */
8121 if (AOP_TYPE (right) == AOP_CRY)
8123 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8124 aopPut (AOP (result), "c", 0);
8130 aopPut (AOP (result), "a", 0);
8134 /* bit variables done */
8136 size = AOP_SIZE (result);
8138 if (AOP_TYPE (right) == AOP_LIT)
8139 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8141 (AOP_TYPE (result) != AOP_REG) &&
8142 (AOP_TYPE (right) == AOP_LIT) &&
8143 !IS_FLOAT (operandType (right)) &&
8146 emitcode ("clr", "a");
8149 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8150 aopPut (AOP (result), "a", size);
8152 aopPut (AOP (result),
8153 aopGet (AOP (right), size, FALSE, FALSE),
8161 aopPut (AOP (result),
8162 aopGet (AOP (right), offset, FALSE, FALSE),
8169 freeAsmop (right, NULL, ic, TRUE);
8170 freeAsmop (result, NULL, ic, TRUE);
8173 /*-----------------------------------------------------------------*/
8174 /* genJumpTab - genrates code for jump table */
8175 /*-----------------------------------------------------------------*/
8177 genJumpTab (iCode * ic)
8182 aopOp (IC_JTCOND (ic), ic, FALSE);
8183 /* get the condition into accumulator */
8184 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8186 /* multiply by three */
8187 emitcode ("add", "a,acc");
8188 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8189 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8191 jtab = newiTempLabel (NULL);
8192 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8193 emitcode ("jmp", "@a+dptr");
8194 emitcode ("", "%05d$:", jtab->key + 100);
8195 /* now generate the jump labels */
8196 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8197 jtab = setNextItem (IC_JTLABELS (ic)))
8198 emitcode ("ljmp", "%05d$", jtab->key + 100);
8202 /*-----------------------------------------------------------------*/
8203 /* genCast - gen code for casting */
8204 /*-----------------------------------------------------------------*/
8206 genCast (iCode * ic)
8208 operand *result = IC_RESULT (ic);
8209 sym_link *ctype = operandType (IC_LEFT (ic));
8210 sym_link *rtype = operandType (IC_RIGHT (ic));
8211 operand *right = IC_RIGHT (ic);
8214 D(emitcode(";", "genCast"));
8216 /* if they are equivalent then do nothing */
8217 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8220 aopOp (right, ic, FALSE);
8221 aopOp (result, ic, FALSE);
8223 /* if the result is a bit */
8224 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8225 if (IS_BITVAR(OP_SYMBOL(result)->type))
8227 /* if the right size is a literal then
8228 we know what the value is */
8229 if (AOP_TYPE (right) == AOP_LIT)
8231 if (((int) operandLitValue (right)))
8232 aopPut (AOP (result), one, 0);
8234 aopPut (AOP (result), zero, 0);
8239 /* the right is also a bit variable */
8240 if (AOP_TYPE (right) == AOP_CRY)
8242 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8243 aopPut (AOP (result), "c", 0);
8249 aopPut (AOP (result), "a", 0);
8253 /* if they are the same size : or less */
8254 if (AOP_SIZE (result) <= AOP_SIZE (right))
8257 /* if they are in the same place */
8258 if (sameRegs (AOP (right), AOP (result)))
8261 /* if they in different places then copy */
8262 size = AOP_SIZE (result);
8266 aopPut (AOP (result),
8267 aopGet (AOP (right), offset, FALSE, FALSE),
8275 /* if the result is of type pointer */
8280 sym_link *type = operandType (right);
8281 sym_link *etype = getSpec (type);
8283 /* pointer to generic pointer */
8284 if (IS_GENPTR (ctype))
8289 p_type = DCL_TYPE (type);
8292 if (SPEC_SCLS(etype)==S_REGISTER) {
8293 // let's assume it is a generic pointer
8296 /* we have to go by the storage class */
8297 p_type = PTR_TYPE (SPEC_OCLS (etype));
8301 /* the first two bytes are known */
8302 size = GPTRSIZE - 1;
8306 aopPut (AOP (result),
8307 aopGet (AOP (right), offset, FALSE, FALSE),
8311 /* the last byte depending on type */
8327 case PPOINTER: // what the fck is this?
8332 /* this should never happen */
8333 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8334 "got unknown pointer type");
8337 aopPut (AOP (result), l, GPTRSIZE - 1);
8341 /* just copy the pointers */
8342 size = AOP_SIZE (result);
8346 aopPut (AOP (result),
8347 aopGet (AOP (right), offset, FALSE, FALSE),
8354 /* so we now know that the size of destination is greater
8355 than the size of the source */
8356 /* we move to result for the size of source */
8357 size = AOP_SIZE (right);
8361 aopPut (AOP (result),
8362 aopGet (AOP (right), offset, FALSE, FALSE),
8367 /* now depending on the sign of the source && destination */
8368 size = AOP_SIZE (result) - AOP_SIZE (right);
8369 /* if unsigned or not an integral type */
8370 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8373 aopPut (AOP (result), zero, offset++);
8377 /* we need to extend the sign :{ */
8378 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8381 emitcode ("rlc", "a");
8382 emitcode ("subb", "a,acc");
8384 aopPut (AOP (result), "a", offset++);
8387 /* we are done hurray !!!! */
8390 freeAsmop (right, NULL, ic, TRUE);
8391 freeAsmop (result, NULL, ic, TRUE);
8395 /*-----------------------------------------------------------------*/
8396 /* genDjnz - generate decrement & jump if not zero instrucion */
8397 /*-----------------------------------------------------------------*/
8399 genDjnz (iCode * ic, iCode * ifx)
8405 /* if the if condition has a false label
8406 then we cannot save */
8410 /* if the minus is not of the form
8412 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8413 !IS_OP_LITERAL (IC_RIGHT (ic)))
8416 if (operandLitValue (IC_RIGHT (ic)) != 1)
8419 /* if the size of this greater than one then no
8421 if (getSize (operandType (IC_RESULT (ic))) > 1)
8424 /* otherwise we can save BIG */
8425 lbl = newiTempLabel (NULL);
8426 lbl1 = newiTempLabel (NULL);
8428 aopOp (IC_RESULT (ic), ic, FALSE);
8430 if (AOP_NEEDSACC(IC_RESULT(ic)))
8432 /* If the result is accessed indirectly via
8433 * the accumulator, we must explicitly write
8434 * it back after the decrement.
8436 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8438 if (strcmp(rByte, "a"))
8440 /* Something is hopelessly wrong */
8441 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8442 __FILE__, __LINE__);
8443 /* We can just give up; the generated code will be inefficient,
8446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8449 emitcode ("dec", "%s", rByte);
8450 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8451 emitcode ("jnz", "%05d$", lbl->key + 100);
8453 else if (IS_AOP_PREG (IC_RESULT (ic)))
8455 emitcode ("dec", "%s",
8456 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8457 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8458 emitcode ("jnz", "%05d$", lbl->key + 100);
8462 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8465 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8466 emitcode ("", "%05d$:", lbl->key + 100);
8467 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8468 emitcode ("", "%05d$:", lbl1->key + 100);
8470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genReceive - generate code for a receive iCode */
8477 /*-----------------------------------------------------------------*/
8479 genReceive (iCode * ic)
8481 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8482 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8483 IS_TRUE_SYMOP (IC_RESULT (ic))))
8486 int size = getSize (operandType (IC_RESULT (ic)));
8487 int offset = fReturnSizeMCS51 - size;
8490 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8491 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8494 aopOp (IC_RESULT (ic), ic, FALSE);
8495 size = AOP_SIZE (IC_RESULT (ic));
8499 emitcode ("pop", "acc");
8500 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8507 aopOp (IC_RESULT (ic), ic, FALSE);
8509 assignResultValue (IC_RESULT (ic));
8512 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8515 /*-----------------------------------------------------------------*/
8516 /* gen51AggregateAssign - copy complete array's or structures */
8517 /*-----------------------------------------------------------------*/
8518 void gen51AggregateAssign(iCode *ic) {
8519 operand *left=IC_LEFT(ic);
8520 operand *right=IC_RIGHT(ic);
8521 char *fromName=OP_SYMBOL(right)->rname;
8522 char *toName=OP_SYMBOL(left)->rname;
8523 int fromSize=getSize(OP_SYMBOL(right)->type);
8524 int toSize=getSize(OP_SYMBOL(left)->type);
8527 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8528 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8529 // well, this code isn't used yet from anywhere else as for initialising
8530 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8534 if (fromSize!=toSize) {
8535 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8536 ic->filename, ic->lineno);
8541 // use the generic memcpy() for now
8542 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8543 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8544 emitcode ("mov", "a,#%s", fromName);
8545 emitcode ("movx", "@dptr,a");
8546 emitcode ("inc", "dptr");
8547 emitcode ("mov", "a,#(%s>>8)", fromName);
8548 emitcode ("movx", "@dptr,a");
8549 emitcode ("inc", "dptr");
8550 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8551 emitcode ("movx", "@dptr,a");
8552 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8553 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8554 emitcode ("movx", "@dptr,a");
8555 emitcode ("inc", "dptr");
8556 emitcode ("mov", "a,#(%d>>8)", count);
8557 emitcode ("movx", "@dptr,a");
8558 emitcode ("mov", "dptr,#%s", toName);
8559 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8560 emitcode ("lcall", "_memcpy");
8562 // more efficient, but will require the native_memcpy_cs2xs
8563 emitcode ("mov", "r0,#%s", fromName);
8564 emitcode ("mov", "r1,#(%s>>8)", fromName);
8565 emitcode ("mov", "r2,#%s", toName);
8566 emitcode ("mov", "r3,#(%s>>8)", toName);
8567 emitcode ("mov", "r4,#%d", count);
8568 emitcode ("mov", "r5,#(%d>>8)", count);
8569 emitcode ("lcall", "_native_memcpy_cs2xs");
8573 /*-----------------------------------------------------------------*/
8574 /* gen51Code - generate code for 8051 based controllers */
8575 /*-----------------------------------------------------------------*/
8577 gen51Code (iCode * lic)
8582 lineHead = lineCurr = NULL;
8584 /* print the allocation information */
8586 printAllocInfo (currFunc, codeOutFile);
8587 /* if debug information required */
8588 /* if (options.debug && currFunc) { */
8589 if (options.debug && currFunc)
8591 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8593 if (IS_STATIC (currFunc->etype))
8594 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8596 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8599 /* stack pointer name */
8600 if (options.useXstack)
8606 for (ic = lic; ic; ic = ic->next)
8609 if (cln != ic->lineno)
8614 emitcode ("", "C$%s$%d$%d$%d ==.",
8615 FileBaseName (ic->filename), ic->lineno,
8616 ic->level, ic->block);
8619 emitcode (";", "%s %d", ic->filename, ic->lineno);
8622 /* if the result is marked as
8623 spilt and rematerializable or code for
8624 this has already been generated then
8626 if (resultRemat (ic) || ic->generated)
8629 /* depending on the operation */
8649 /* IPOP happens only when trying to restore a
8650 spilt live range, if there is an ifx statement
8651 following this pop then the if statement might
8652 be using some of the registers being popped which
8653 would destory the contents of the register so
8654 we need to check for this condition and handle it */
8656 ic->next->op == IFX &&
8657 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8658 genIfx (ic->next, ic);
8676 genEndFunction (ic);
8696 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8713 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8717 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8724 /* note these two are xlated by algebraic equivalence
8725 during parsing SDCC.y */
8726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8727 "got '>=' or '<=' shouldn't have come here");
8731 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8743 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8747 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8751 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8778 case GET_VALUE_AT_ADDRESS:
8779 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8783 if (POINTER_SET (ic))
8784 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8810 addSet (&_G.sendSet, ic);
8814 gen51AggregateAssign(ic);
8823 /* now we are ready to call the
8824 peep hole optimizer */
8825 if (!options.nopeep)
8826 peepHole (&lineHead);
8828 /* now do the actual printing */
8829 printLine (lineHead, codeOutFile);