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 || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1460 SPEC_NAKED(OP_SYM_ETYPE(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 detype = getSpec (operandType (IC_LEFT (ic)));
1884 if (detype && !SPEC_NAKED(detype) &&
1885 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1886 IS_ISR (currFunc->etype))
1890 /* This is unexpected; the bank should have been saved in
1893 saveRBank (SPEC_BANK (detype), ic, FALSE);
1899 /* if caller saves & we have not saved then */
1905 emitcode ("mov", "psw,#0x%02x",
1906 ((SPEC_BANK(detype)) << 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 ((SPEC_BANK(currFunc->etype)) << 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 && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1954 unsaveRegisters (ic);
1956 /* if register bank was saved then pop them */
1958 unsaveRBank (SPEC_BANK (detype), 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 detype = getSpec (operandType (IC_LEFT (ic)));
1980 IS_ISR (currFunc->etype) &&
1981 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1982 saveRBank (SPEC_BANK (detype), 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 (SPEC_BANK (currFunc->etype) !=
2064 SPEC_BANK (detype)))
2065 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2067 /* if we hade saved some registers then
2070 unsaveRegisters (ic);
2074 /*-----------------------------------------------------------------*/
2075 /* resultRemat - result is rematerializable */
2076 /*-----------------------------------------------------------------*/
2078 resultRemat (iCode * ic)
2080 if (SKIP_IC (ic) || ic->op == IFX)
2083 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2085 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2086 if (sym->remat && !POINTER_SET (ic))
2093 #if defined(__BORLANDC__) || defined(_MSC_VER)
2094 #define STRCASECMP stricmp
2096 #define STRCASECMP strcasecmp
2099 /*-----------------------------------------------------------------*/
2100 /* inExcludeList - return 1 if the string is in exclude Reg list */
2101 /*-----------------------------------------------------------------*/
2103 inExcludeList (char *s)
2107 if (options.excludeRegs[i] &&
2108 STRCASECMP (options.excludeRegs[i], "none") == 0)
2111 for (i = 0; options.excludeRegs[i]; i++)
2113 if (options.excludeRegs[i] &&
2114 STRCASECMP (s, options.excludeRegs[i]) == 0)
2120 /*-----------------------------------------------------------------*/
2121 /* genFunction - generated code for function entry */
2122 /*-----------------------------------------------------------------*/
2124 genFunction (iCode * ic)
2128 bool switchedPSW = FALSE;
2131 /* create the function header */
2132 emitcode (";", "-----------------------------------------");
2133 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2134 emitcode (";", "-----------------------------------------");
2136 emitcode ("", "%s:", sym->rname);
2137 fetype = getSpec (operandType (IC_LEFT (ic)));
2139 if (SPEC_NAKED(fetype))
2141 emitcode(";", "naked function: no prologue.");
2145 /* if critical function then turn interrupts off */
2146 if (SPEC_CRTCL (fetype))
2147 emitcode ("clr", "ea");
2149 /* here we need to generate the equates for the
2150 register bank if required */
2151 if (SPEC_BANK (fetype) != rbank)
2155 rbank = SPEC_BANK (fetype);
2156 for (i = 0; i < mcs51_nRegs; i++)
2158 if (strcmp (regs8051[i].base, "0") == 0)
2159 emitcode ("", "%s = 0x%02x",
2161 8 * rbank + regs8051[i].offset);
2163 emitcode ("", "%s = %s + 0x%02x",
2166 8 * rbank + regs8051[i].offset);
2170 /* if this is an interrupt service routine then
2171 save acc, b, dpl, dph */
2172 if (IS_ISR (sym->etype))
2175 if (!inExcludeList ("acc"))
2176 emitcode ("push", "acc");
2177 if (!inExcludeList ("b"))
2178 emitcode ("push", "b");
2179 if (!inExcludeList ("dpl"))
2180 emitcode ("push", "dpl");
2181 if (!inExcludeList ("dph"))
2182 emitcode ("push", "dph");
2183 /* if this isr has no bank i.e. is going to
2184 run with bank 0 , then we need to save more
2186 if (!SPEC_BANK (sym->etype))
2189 /* if this function does not call any other
2190 function then we can be economical and
2191 save only those registers that are used */
2196 /* if any registers used */
2199 /* save the registers used */
2200 for (i = 0; i < sym->regsUsed->size; i++)
2202 if (bitVectBitValue (sym->regsUsed, i) ||
2203 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2204 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2211 /* this function has a function call cannot
2212 determines register usage so we will have to push the
2214 saveRBank (0, ic, FALSE);
2219 /* This ISR uses a non-zero bank.
2221 * We assume that the bank is available for our
2224 * However, if this ISR calls a function which uses some
2225 * other bank, we must save that bank entirely.
2227 unsigned long banksToSave = 0;
2232 #define MAX_REGISTER_BANKS 4
2237 for (i = ic; i; i = i->next)
2239 if (i->op == ENDFUNCTION)
2241 /* we got to the end OK. */
2249 detype = getSpec(operandType (IC_LEFT(i)));
2251 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2253 /* Mark this bank for saving. */
2254 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2256 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2260 banksToSave |= (1 << SPEC_BANK(detype));
2263 /* And note that we don't need to do it in
2271 /* This is a mess; we have no idea what
2272 * register bank the called function might
2275 * The only thing I can think of to do is
2276 * throw a warning and hope.
2278 werror(W_FUNCPTR_IN_USING_ISR);
2282 if (banksToSave && options.useXstack)
2284 /* Since we aren't passing it an ic,
2285 * saveRBank will assume r0 is available to abuse.
2287 * So switch to our (trashable) bank now, so
2288 * the caller's R0 isn't trashed.
2290 emitcode ("push", "psw");
2291 emitcode ("mov", "psw,#0x%02x",
2292 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2296 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2298 if (banksToSave & (1 << ix))
2300 saveRBank(ix, NULL, FALSE);
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 (sym->calleeSave)
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 ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2336 emitcode ("push", "psw");
2337 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2340 if (IS_RENT (sym->etype) || 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 (SPEC_NAKED(sym->etype))
2399 emitcode(";", "naked function: no epilogue.");
2403 if (IS_RENT (sym->etype) || 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 ((IS_RENT (sym->etype) || 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 (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2437 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2438 || !options.useXstack)
2440 /* Special case of ISR using non-zero bank with useXstack
2443 emitcode ("pop", "psw");
2447 if (IS_ISR (sym->etype))
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 (!SPEC_BANK (sym->etype))
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 */
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 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2494 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2496 if (savedBanks & (1 << ix))
2498 unsaveRBank(ix, NULL, FALSE);
2502 if (options.useXstack)
2504 /* Restore bank AFTER calling unsaveRBank,
2505 * since it can trash r0.
2507 emitcode ("pop", "psw");
2511 if (!inExcludeList ("dph"))
2512 emitcode ("pop", "dph");
2513 if (!inExcludeList ("dpl"))
2514 emitcode ("pop", "dpl");
2515 if (!inExcludeList ("b"))
2516 emitcode ("pop", "b");
2517 if (!inExcludeList ("acc"))
2518 emitcode ("pop", "acc");
2520 if (SPEC_CRTCL (sym->etype))
2521 emitcode ("setb", "ea");
2523 /* if debug then send end of function */
2524 /* if (options.debug && currFunc) */
2525 if (options.debug && currFunc)
2528 emitcode ("", "C$%s$%d$%d$%d ==.",
2529 FileBaseName (ic->filename), currFunc->lastLine,
2530 ic->level, ic->block);
2531 if (IS_STATIC (currFunc->etype))
2532 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2534 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2538 emitcode ("reti", "");
2542 if (SPEC_CRTCL (sym->etype))
2543 emitcode ("setb", "ea");
2545 if (sym->calleeSave)
2549 /* if any registers used */
2552 /* save the registers used */
2553 for (i = sym->regsUsed->size; i >= 0; i--)
2555 if (bitVectBitValue (sym->regsUsed, i) ||
2556 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2557 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2563 /* if debug then send end of function */
2564 if (options.debug && currFunc)
2567 emitcode ("", "C$%s$%d$%d$%d ==.",
2568 FileBaseName (ic->filename), currFunc->lastLine,
2569 ic->level, ic->block);
2570 if (IS_STATIC (currFunc->etype))
2571 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2573 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2577 emitcode ("ret", "");
2582 /*-----------------------------------------------------------------*/
2583 /* genRet - generate code for return statement */
2584 /*-----------------------------------------------------------------*/
2588 int size, offset = 0, pushed = 0;
2590 /* if we have no return value then
2591 just generate the "ret" */
2595 /* we have something to return then
2596 move the return value into place */
2597 aopOp (IC_LEFT (ic), ic, FALSE);
2598 size = AOP_SIZE (IC_LEFT (ic));
2603 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2606 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2608 emitcode ("push", "%s", l);
2613 l = aopGet (AOP (IC_LEFT (ic)), offset,
2615 if (strcmp (fReturn[offset], l))
2616 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2625 if (strcmp (fReturn[pushed], "a"))
2626 emitcode ("pop", fReturn[pushed]);
2628 emitcode ("pop", "acc");
2631 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2634 /* generate a jump to the return label
2635 if the next is not the return statement */
2636 if (!(ic->next && ic->next->op == LABEL &&
2637 IC_LABEL (ic->next) == returnLabel))
2639 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2643 /*-----------------------------------------------------------------*/
2644 /* genLabel - generates a label */
2645 /*-----------------------------------------------------------------*/
2647 genLabel (iCode * ic)
2649 /* special case never generate */
2650 if (IC_LABEL (ic) == entryLabel)
2653 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2656 /*-----------------------------------------------------------------*/
2657 /* genGoto - generates a ljmp */
2658 /*-----------------------------------------------------------------*/
2660 genGoto (iCode * ic)
2662 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2665 /*-----------------------------------------------------------------*/
2666 /* findLabelBackwards: walks back through the iCode chain looking */
2667 /* for the given label. Returns number of iCode instructions */
2668 /* between that label and given ic. */
2669 /* Returns zero if label not found. */
2670 /*-----------------------------------------------------------------*/
2672 findLabelBackwards (iCode * ic, int key)
2681 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2683 /* printf("findLabelBackwards = %d\n", count); */
2691 /*-----------------------------------------------------------------*/
2692 /* genPlusIncr :- does addition with increment if possible */
2693 /*-----------------------------------------------------------------*/
2695 genPlusIncr (iCode * ic)
2697 unsigned int icount;
2698 unsigned int size = getDataSize (IC_RESULT (ic));
2700 /* will try to generate an increment */
2701 /* if the right side is not a literal
2703 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2706 /* if the literal value of the right hand side
2707 is greater than 4 then it is not worth it */
2708 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2711 /* if increment 16 bits in register */
2712 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2720 /* If the next instruction is a goto and the goto target
2721 * is < 10 instructions previous to this, we can generate
2722 * jumps straight to that target.
2724 if (ic->next && ic->next->op == GOTO
2725 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2726 && labelRange <= 10)
2728 emitcode (";", "tail increment optimized");
2729 tlbl = IC_LABEL (ic->next);
2734 tlbl = newiTempLabel (NULL);
2737 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2738 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2739 IS_AOP_PREG (IC_RESULT (ic)))
2740 emitcode ("cjne", "%s,#0x00,%05d$"
2741 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2745 emitcode ("clr", "a");
2746 emitcode ("cjne", "a,%s,%05d$"
2747 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2751 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2754 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2755 IS_AOP_PREG (IC_RESULT (ic)))
2756 emitcode ("cjne", "%s,#0x00,%05d$"
2757 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2760 emitcode ("cjne", "a,%s,%05d$"
2761 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2764 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2768 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2769 IS_AOP_PREG (IC_RESULT (ic)))
2770 emitcode ("cjne", "%s,#0x00,%05d$"
2771 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2775 emitcode ("cjne", "a,%s,%05d$"
2776 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2779 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2784 emitcode ("", "%05d$:", tlbl->key + 100);
2789 /* if the sizes are greater than 1 then we cannot */
2790 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2791 AOP_SIZE (IC_LEFT (ic)) > 1)
2794 /* we can if the aops of the left & result match or
2795 if they are in registers and the registers are the
2797 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2802 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2803 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2804 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2810 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2819 /*-----------------------------------------------------------------*/
2820 /* outBitAcc - output a bit in acc */
2821 /*-----------------------------------------------------------------*/
2823 outBitAcc (operand * result)
2825 symbol *tlbl = newiTempLabel (NULL);
2826 /* if the result is a bit */
2827 if (AOP_TYPE (result) == AOP_CRY)
2829 aopPut (AOP (result), "a", 0);
2833 emitcode ("jz", "%05d$", tlbl->key + 100);
2834 emitcode ("mov", "a,%s", one);
2835 emitcode ("", "%05d$:", tlbl->key + 100);
2840 /*-----------------------------------------------------------------*/
2841 /* genPlusBits - generates code for addition of two bits */
2842 /*-----------------------------------------------------------------*/
2844 genPlusBits (iCode * ic)
2846 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2848 symbol *lbl = newiTempLabel (NULL);
2849 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2850 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2851 emitcode ("cpl", "c");
2852 emitcode ("", "%05d$:", (lbl->key + 100));
2853 outBitC (IC_RESULT (ic));
2857 emitcode ("clr", "a");
2858 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2859 emitcode ("rlc", "a");
2860 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2861 emitcode ("addc", "a,#0x00");
2862 outAcc (IC_RESULT (ic));
2867 /* This is the original version of this code.
2869 * This is being kept around for reference,
2870 * because I am not entirely sure I got it right...
2873 adjustArithmeticResult (iCode * ic)
2875 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2876 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2877 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2878 aopPut (AOP (IC_RESULT (ic)),
2879 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2882 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2883 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2884 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2885 aopPut (AOP (IC_RESULT (ic)),
2886 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2889 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2890 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2891 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2892 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2893 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2896 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2897 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2901 /* This is the pure and virtuous version of this code.
2902 * I'm pretty certain it's right, but not enough to toss the old
2906 adjustArithmeticResult (iCode * ic)
2908 if (opIsGptr (IC_RESULT (ic)) &&
2909 opIsGptr (IC_LEFT (ic)) &&
2910 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2912 aopPut (AOP (IC_RESULT (ic)),
2913 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2917 if (opIsGptr (IC_RESULT (ic)) &&
2918 opIsGptr (IC_RIGHT (ic)) &&
2919 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2921 aopPut (AOP (IC_RESULT (ic)),
2922 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2926 if (opIsGptr (IC_RESULT (ic)) &&
2927 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2928 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2930 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2933 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2934 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2939 /*-----------------------------------------------------------------*/
2940 /* genPlus - generates code for addition */
2941 /*-----------------------------------------------------------------*/
2943 genPlus (iCode * ic)
2945 int size, offset = 0;
2947 /* special cases :- */
2949 aopOp (IC_LEFT (ic), ic, FALSE);
2950 aopOp (IC_RIGHT (ic), ic, FALSE);
2951 aopOp (IC_RESULT (ic), ic, TRUE);
2953 /* if literal, literal on the right or
2954 if left requires ACC or right is already
2956 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2957 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2958 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2960 operand *t = IC_RIGHT (ic);
2961 IC_RIGHT (ic) = IC_LEFT (ic);
2965 /* if both left & right are in bit
2967 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2968 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2974 /* if left in bit space & right literal */
2975 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2976 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2978 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2979 /* if result in bit space */
2980 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2982 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2983 emitcode ("cpl", "c");
2984 outBitC (IC_RESULT (ic));
2988 size = getDataSize (IC_RESULT (ic));
2991 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2992 emitcode ("addc", "a,#00");
2993 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2999 /* if I can do an increment instead
3000 of add then GOOD for ME */
3001 if (genPlusIncr (ic) == TRUE)
3004 size = getDataSize (IC_RESULT (ic));
3008 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3010 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3012 emitcode ("add", "a,%s",
3013 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3015 emitcode ("addc", "a,%s",
3016 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3020 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3022 emitcode ("add", "a,%s",
3023 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3025 emitcode ("addc", "a,%s",
3026 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3028 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3031 adjustArithmeticResult (ic);
3034 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3035 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3039 /*-----------------------------------------------------------------*/
3040 /* genMinusDec :- does subtraction with deccrement if possible */
3041 /*-----------------------------------------------------------------*/
3043 genMinusDec (iCode * ic)
3045 unsigned int icount;
3046 unsigned int size = getDataSize (IC_RESULT (ic));
3048 /* will try to generate an increment */
3049 /* if the right side is not a literal
3051 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3054 /* if the literal value of the right hand side
3055 is greater than 4 then it is not worth it */
3056 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3059 /* if decrement 16 bits in register */
3060 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3068 /* If the next instruction is a goto and the goto target
3069 * is <= 10 instructions previous to this, we can generate
3070 * jumps straight to that target.
3072 if (ic->next && ic->next->op == GOTO
3073 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3074 && labelRange <= 10)
3076 emitcode (";", "tail decrement optimized");
3077 tlbl = IC_LABEL (ic->next);
3082 tlbl = newiTempLabel (NULL);
3086 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3087 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3088 IS_AOP_PREG (IC_RESULT (ic)))
3089 emitcode ("cjne", "%s,#0xff,%05d$"
3090 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3094 emitcode ("mov", "a,#0xff");
3095 emitcode ("cjne", "a,%s,%05d$"
3096 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3099 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3102 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3103 IS_AOP_PREG (IC_RESULT (ic)))
3104 emitcode ("cjne", "%s,#0xff,%05d$"
3105 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3109 emitcode ("cjne", "a,%s,%05d$"
3110 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3113 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3117 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3118 IS_AOP_PREG (IC_RESULT (ic)))
3119 emitcode ("cjne", "%s,#0xff,%05d$"
3120 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3124 emitcode ("cjne", "a,%s,%05d$"
3125 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3128 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3132 emitcode ("", "%05d$:", tlbl->key + 100);
3137 /* if the sizes are greater than 1 then we cannot */
3138 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3139 AOP_SIZE (IC_LEFT (ic)) > 1)
3142 /* we can if the aops of the left & result match or
3143 if they are in registers and the registers are the
3145 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3149 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3157 /*-----------------------------------------------------------------*/
3158 /* addSign - complete with sign */
3159 /*-----------------------------------------------------------------*/
3161 addSign (operand * result, int offset, int sign)
3163 int size = (getDataSize (result) - offset);
3168 emitcode ("rlc", "a");
3169 emitcode ("subb", "a,acc");
3171 aopPut (AOP (result), "a", offset++);
3175 aopPut (AOP (result), zero, offset++);
3179 /*-----------------------------------------------------------------*/
3180 /* genMinusBits - generates code for subtraction of two bits */
3181 /*-----------------------------------------------------------------*/
3183 genMinusBits (iCode * ic)
3185 symbol *lbl = newiTempLabel (NULL);
3186 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3188 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3189 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3190 emitcode ("cpl", "c");
3191 emitcode ("", "%05d$:", (lbl->key + 100));
3192 outBitC (IC_RESULT (ic));
3196 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3197 emitcode ("subb", "a,acc");
3198 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3199 emitcode ("inc", "a");
3200 emitcode ("", "%05d$:", (lbl->key + 100));
3201 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3202 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3206 /*-----------------------------------------------------------------*/
3207 /* genMinus - generates code for subtraction */
3208 /*-----------------------------------------------------------------*/
3210 genMinus (iCode * ic)
3212 int size, offset = 0;
3213 unsigned long lit = 0L;
3215 aopOp (IC_LEFT (ic), ic, FALSE);
3216 aopOp (IC_RIGHT (ic), ic, FALSE);
3217 aopOp (IC_RESULT (ic), ic, TRUE);
3219 /* special cases :- */
3220 /* if both left & right are in bit space */
3221 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3222 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3228 /* if I can do an decrement instead
3229 of subtract then GOOD for ME */
3230 if (genMinusDec (ic) == TRUE)
3233 size = getDataSize (IC_RESULT (ic));
3235 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3241 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3245 /* if literal, add a,#-lit, else normal subb */
3248 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3249 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3250 emitcode ("subb", "a,%s",
3251 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3254 /* first add without previous c */
3256 if (!size && lit==-1) {
3257 emitcode ("dec", "a");
3259 emitcode ("add", "a,#0x%02x",
3260 (unsigned int) (lit & 0x0FFL));
3263 emitcode ("addc", "a,#0x%02x",
3264 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3267 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3270 adjustArithmeticResult (ic);
3273 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3274 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3279 /*-----------------------------------------------------------------*/
3280 /* genMultbits :- multiplication of bits */
3281 /*-----------------------------------------------------------------*/
3283 genMultbits (operand * left,
3287 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3288 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3293 /*-----------------------------------------------------------------*/
3294 /* genMultOneByte : 8*8=8/16 bit multiplication */
3295 /*-----------------------------------------------------------------*/
3297 genMultOneByte (operand * left,
3301 sym_link *opetype = operandType (result);
3303 int size=AOP_SIZE(result);
3305 if (size<1 || size>2) {
3306 // this should never happen
3307 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3308 AOP_SIZE(result), __FILE__, lineno);
3312 /* (if two literals: the value is computed before) */
3313 /* if one literal, literal on the right */
3314 if (AOP_TYPE (left) == AOP_LIT)
3319 //emitcode (";", "swapped left and right");
3322 if (SPEC_USIGN(opetype)
3323 // ignore the sign of left and right, what else can we do?
3324 || (SPEC_USIGN(operandType(left)) &&
3325 SPEC_USIGN(operandType(right)))) {
3326 // just an unsigned 8*8=8/16 multiply
3327 //emitcode (";","unsigned");
3328 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3329 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3330 emitcode ("mul", "ab");
3331 aopPut (AOP (result), "a", 0);
3333 aopPut (AOP (result), "b", 1);
3338 // we have to do a signed multiply
3340 //emitcode (";", "signed");
3341 emitcode ("clr", "F0"); // reset sign flag
3342 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3344 lbl=newiTempLabel(NULL);
3345 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3346 // left side is negative, 8-bit two's complement, this fails for -128
3347 emitcode ("setb", "F0"); // set sign flag
3348 emitcode ("cpl", "a");
3349 emitcode ("inc", "a");
3351 emitcode ("", "%05d$:", lbl->key+100);
3354 if (AOP_TYPE(right)==AOP_LIT) {
3355 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3356 /* AND literal negative */
3358 emitcode ("cpl", "F0"); // complement sign flag
3359 emitcode ("mov", "b,#0x%02x", -val);
3361 emitcode ("mov", "b,#0x%02x", val);
3364 lbl=newiTempLabel(NULL);
3365 emitcode ("mov", "b,a");
3366 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3367 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3368 // right side is negative, 8-bit two's complement
3369 emitcode ("cpl", "F0"); // complement sign flag
3370 emitcode ("cpl", "a");
3371 emitcode ("inc", "a");
3372 emitcode ("", "%05d$:", lbl->key+100);
3374 emitcode ("mul", "ab");
3376 lbl=newiTempLabel(NULL);
3377 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3378 // only ONE op was negative, we have to do a 8/16-bit two's complement
3379 emitcode ("cpl", "a"); // lsb
3381 emitcode ("inc", "a");
3383 emitcode ("add", "a,#1");
3384 emitcode ("xch", "a,b");
3385 emitcode ("cpl", "a"); // msb
3386 emitcode ("addc", "a,#0");
3387 emitcode ("xch", "a,b");
3390 emitcode ("", "%05d$:", lbl->key+100);
3391 aopPut (AOP (result), "a", 0);
3393 aopPut (AOP (result), "b", 1);
3397 /*-----------------------------------------------------------------*/
3398 /* genMult - generates code for multiplication */
3399 /*-----------------------------------------------------------------*/
3401 genMult (iCode * ic)
3403 operand *left = IC_LEFT (ic);
3404 operand *right = IC_RIGHT (ic);
3405 operand *result = IC_RESULT (ic);
3407 /* assign the amsops */
3408 aopOp (left, ic, FALSE);
3409 aopOp (right, ic, FALSE);
3410 aopOp (result, ic, TRUE);
3412 /* special cases first */
3414 if (AOP_TYPE (left) == AOP_CRY &&
3415 AOP_TYPE (right) == AOP_CRY)
3417 genMultbits (left, right, result);
3421 /* if both are of size == 1 */
3422 if (AOP_SIZE (left) == 1 &&
3423 AOP_SIZE (right) == 1)
3425 genMultOneByte (left, right, result);
3429 /* should have been converted to function call */
3433 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3435 freeAsmop (result, NULL, ic, TRUE);
3438 /*-----------------------------------------------------------------*/
3439 /* genDivbits :- division of bits */
3440 /*-----------------------------------------------------------------*/
3442 genDivbits (operand * left,
3449 /* the result must be bit */
3450 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3451 l = aopGet (AOP (left), 0, FALSE, FALSE);
3455 emitcode ("div", "ab");
3456 emitcode ("rrc", "a");
3457 aopPut (AOP (result), "c", 0);
3460 /*-----------------------------------------------------------------*/
3461 /* genDivOneByte : 8 bit division */
3462 /*-----------------------------------------------------------------*/
3464 genDivOneByte (operand * left,
3468 sym_link *opetype = operandType (result);
3473 size = AOP_SIZE (result) - 1;
3475 /* signed or unsigned */
3476 if (SPEC_USIGN (opetype))
3478 /* unsigned is easy */
3479 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3480 l = aopGet (AOP (left), 0, FALSE, FALSE);
3482 emitcode ("div", "ab");
3483 aopPut (AOP (result), "a", 0);
3485 aopPut (AOP (result), zero, offset++);
3489 /* signed is a little bit more difficult */
3491 /* save the signs of the operands */
3492 l = aopGet (AOP (left), 0, FALSE, FALSE);
3494 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3495 emitcode ("push", "acc"); /* save it on the stack */
3497 /* now sign adjust for both left & right */
3498 l = aopGet (AOP (right), 0, FALSE, FALSE);
3500 lbl = newiTempLabel (NULL);
3501 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3502 emitcode ("cpl", "a");
3503 emitcode ("inc", "a");
3504 emitcode ("", "%05d$:", (lbl->key + 100));
3505 emitcode ("mov", "b,a");
3507 /* sign adjust left side */
3508 l = aopGet (AOP (left), 0, FALSE, FALSE);
3511 lbl = newiTempLabel (NULL);
3512 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3513 emitcode ("cpl", "a");
3514 emitcode ("inc", "a");
3515 emitcode ("", "%05d$:", (lbl->key + 100));
3517 /* now the division */
3518 emitcode ("div", "ab");
3519 /* we are interested in the lower order
3521 emitcode ("mov", "b,a");
3522 lbl = newiTempLabel (NULL);
3523 emitcode ("pop", "acc");
3524 /* if there was an over flow we don't
3525 adjust the sign of the result */
3526 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3527 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3529 emitcode ("clr", "a");
3530 emitcode ("subb", "a,b");
3531 emitcode ("mov", "b,a");
3532 emitcode ("", "%05d$:", (lbl->key + 100));
3534 /* now we are done */
3535 aopPut (AOP (result), "b", 0);
3538 emitcode ("mov", "c,b.7");
3539 emitcode ("subb", "a,acc");
3542 aopPut (AOP (result), "a", offset++);
3546 /*-----------------------------------------------------------------*/
3547 /* genDiv - generates code for division */
3548 /*-----------------------------------------------------------------*/
3552 operand *left = IC_LEFT (ic);
3553 operand *right = IC_RIGHT (ic);
3554 operand *result = IC_RESULT (ic);
3556 /* assign the amsops */
3557 aopOp (left, ic, FALSE);
3558 aopOp (right, ic, FALSE);
3559 aopOp (result, ic, TRUE);
3561 /* special cases first */
3563 if (AOP_TYPE (left) == AOP_CRY &&
3564 AOP_TYPE (right) == AOP_CRY)
3566 genDivbits (left, right, result);
3570 /* if both are of size == 1 */
3571 if (AOP_SIZE (left) == 1 &&
3572 AOP_SIZE (right) == 1)
3574 genDivOneByte (left, right, result);
3578 /* should have been converted to function call */
3581 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3582 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3583 freeAsmop (result, NULL, ic, TRUE);
3586 /*-----------------------------------------------------------------*/
3587 /* genModbits :- modulus of bits */
3588 /*-----------------------------------------------------------------*/
3590 genModbits (operand * left,
3597 /* the result must be bit */
3598 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3599 l = aopGet (AOP (left), 0, FALSE, FALSE);
3603 emitcode ("div", "ab");
3604 emitcode ("mov", "a,b");
3605 emitcode ("rrc", "a");
3606 aopPut (AOP (result), "c", 0);
3609 /*-----------------------------------------------------------------*/
3610 /* genModOneByte : 8 bit modulus */
3611 /*-----------------------------------------------------------------*/
3613 genModOneByte (operand * left,
3617 sym_link *opetype = operandType (result);
3621 /* signed or unsigned */
3622 if (SPEC_USIGN (opetype))
3624 /* unsigned is easy */
3625 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3626 l = aopGet (AOP (left), 0, FALSE, FALSE);
3628 emitcode ("div", "ab");
3629 aopPut (AOP (result), "b", 0);
3633 /* signed is a little bit more difficult */
3635 /* save the signs of the operands */
3636 l = aopGet (AOP (left), 0, FALSE, FALSE);
3639 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3640 emitcode ("push", "acc"); /* save it on the stack */
3642 /* now sign adjust for both left & right */
3643 l = aopGet (AOP (right), 0, FALSE, FALSE);
3646 lbl = newiTempLabel (NULL);
3647 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3648 emitcode ("cpl", "a");
3649 emitcode ("inc", "a");
3650 emitcode ("", "%05d$:", (lbl->key + 100));
3651 emitcode ("mov", "b,a");
3653 /* sign adjust left side */
3654 l = aopGet (AOP (left), 0, FALSE, FALSE);
3657 lbl = newiTempLabel (NULL);
3658 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3659 emitcode ("cpl", "a");
3660 emitcode ("inc", "a");
3661 emitcode ("", "%05d$:", (lbl->key + 100));
3663 /* now the multiplication */
3664 emitcode ("div", "ab");
3665 /* we are interested in the lower order
3667 lbl = newiTempLabel (NULL);
3668 emitcode ("pop", "acc");
3669 /* if there was an over flow we don't
3670 adjust the sign of the result */
3671 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3672 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3674 emitcode ("clr", "a");
3675 emitcode ("subb", "a,b");
3676 emitcode ("mov", "b,a");
3677 emitcode ("", "%05d$:", (lbl->key + 100));
3679 /* now we are done */
3680 aopPut (AOP (result), "b", 0);
3684 /*-----------------------------------------------------------------*/
3685 /* genMod - generates code for division */
3686 /*-----------------------------------------------------------------*/
3690 operand *left = IC_LEFT (ic);
3691 operand *right = IC_RIGHT (ic);
3692 operand *result = IC_RESULT (ic);
3694 /* assign the amsops */
3695 aopOp (left, ic, FALSE);
3696 aopOp (right, ic, FALSE);
3697 aopOp (result, ic, TRUE);
3699 /* special cases first */
3701 if (AOP_TYPE (left) == AOP_CRY &&
3702 AOP_TYPE (right) == AOP_CRY)
3704 genModbits (left, right, result);
3708 /* if both are of size == 1 */
3709 if (AOP_SIZE (left) == 1 &&
3710 AOP_SIZE (right) == 1)
3712 genModOneByte (left, right, result);
3716 /* should have been converted to function call */
3720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3721 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3722 freeAsmop (result, NULL, ic, TRUE);
3725 /*-----------------------------------------------------------------*/
3726 /* genIfxJump :- will create a jump depending on the ifx */
3727 /*-----------------------------------------------------------------*/
3729 genIfxJump (iCode * ic, char *jval)
3732 symbol *tlbl = newiTempLabel (NULL);
3735 /* if true label then we jump if condition
3739 jlbl = IC_TRUE (ic);
3740 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3741 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3745 /* false label is present */
3746 jlbl = IC_FALSE (ic);
3747 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3748 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3750 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3751 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3753 emitcode (inst, "%05d$", tlbl->key + 100);
3754 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3755 emitcode ("", "%05d$:", tlbl->key + 100);
3757 /* mark the icode as generated */
3761 /*-----------------------------------------------------------------*/
3762 /* genCmp :- greater or less than comparison */
3763 /*-----------------------------------------------------------------*/
3765 genCmp (operand * left, operand * right,
3766 operand * result, iCode * ifx, int sign, iCode *ic)
3768 int size, offset = 0;
3769 unsigned long lit = 0L;
3771 /* if left & right are bit variables */
3772 if (AOP_TYPE (left) == AOP_CRY &&
3773 AOP_TYPE (right) == AOP_CRY)
3775 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3776 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3780 /* subtract right from left if at the
3781 end the carry flag is set then we know that
3782 left is greater than right */
3783 size = max (AOP_SIZE (left), AOP_SIZE (right));
3785 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3786 if ((size == 1) && !sign &&
3787 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3789 symbol *lbl = newiTempLabel (NULL);
3790 emitcode ("cjne", "%s,%s,%05d$",
3791 aopGet (AOP (left), offset, FALSE, FALSE),
3792 aopGet (AOP (right), offset, FALSE, FALSE),
3794 emitcode ("", "%05d$:", lbl->key + 100);
3798 if (AOP_TYPE (right) == AOP_LIT)
3800 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3801 /* optimize if(x < 0) or if(x >= 0) */
3810 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3811 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3813 genIfxJump (ifx, "acc.7");
3817 emitcode ("rlc", "a");
3825 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3826 if (sign && size == 0)
3828 emitcode ("xrl", "a,#0x80");
3829 if (AOP_TYPE (right) == AOP_LIT)
3831 unsigned long lit = (unsigned long)
3832 floatFromVal (AOP (right)->aopu.aop_lit);
3833 emitcode ("subb", "a,#0x%02x",
3834 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3838 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3839 emitcode ("xrl", "b,#0x80");
3840 emitcode ("subb", "a,b");
3844 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3850 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3851 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3852 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3858 /* if the result is used in the next
3859 ifx conditional branch then generate
3860 code a little differently */
3862 genIfxJump (ifx, "c");
3865 /* leave the result in acc */
3869 /*-----------------------------------------------------------------*/
3870 /* genCmpGt :- greater than comparison */
3871 /*-----------------------------------------------------------------*/
3873 genCmpGt (iCode * ic, iCode * ifx)
3875 operand *left, *right, *result;
3876 sym_link *letype, *retype;
3879 left = IC_LEFT (ic);
3880 right = IC_RIGHT (ic);
3881 result = IC_RESULT (ic);
3883 letype = getSpec (operandType (left));
3884 retype = getSpec (operandType (right));
3885 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3886 /* assign the amsops */
3887 aopOp (left, ic, FALSE);
3888 aopOp (right, ic, FALSE);
3889 aopOp (result, ic, TRUE);
3891 genCmp (right, left, result, ifx, sign,ic);
3893 freeAsmop (result, NULL, ic, TRUE);
3896 /*-----------------------------------------------------------------*/
3897 /* genCmpLt - less than comparisons */
3898 /*-----------------------------------------------------------------*/
3900 genCmpLt (iCode * ic, iCode * ifx)
3902 operand *left, *right, *result;
3903 sym_link *letype, *retype;
3906 left = IC_LEFT (ic);
3907 right = IC_RIGHT (ic);
3908 result = IC_RESULT (ic);
3910 letype = getSpec (operandType (left));
3911 retype = getSpec (operandType (right));
3912 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3914 /* assign the amsops */
3915 aopOp (left, ic, FALSE);
3916 aopOp (right, ic, FALSE);
3917 aopOp (result, ic, TRUE);
3919 genCmp (left, right, result, ifx, sign,ic);
3921 freeAsmop (result, NULL, ic, TRUE);
3924 /*-----------------------------------------------------------------*/
3925 /* gencjneshort - compare and jump if not equal */
3926 /*-----------------------------------------------------------------*/
3928 gencjneshort (operand * left, operand * right, symbol * lbl)
3930 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3932 unsigned long lit = 0L;
3934 /* if the left side is a literal or
3935 if the right is in a pointer register and left
3937 if ((AOP_TYPE (left) == AOP_LIT) ||
3938 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3944 if (AOP_TYPE (right) == AOP_LIT)
3945 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3947 /* if the right side is a literal then anything goes */
3948 if (AOP_TYPE (right) == AOP_LIT &&
3949 AOP_TYPE (left) != AOP_DIR)
3953 emitcode ("cjne", "%s,%s,%05d$",
3954 aopGet (AOP (left), offset, FALSE, FALSE),
3955 aopGet (AOP (right), offset, FALSE, FALSE),
3961 /* if the right side is in a register or in direct space or
3962 if the left is a pointer register & right is not */
3963 else if (AOP_TYPE (right) == AOP_REG ||
3964 AOP_TYPE (right) == AOP_DIR ||
3965 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3966 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3970 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3971 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3972 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3973 emitcode ("jnz", "%05d$", lbl->key + 100);
3975 emitcode ("cjne", "a,%s,%05d$",
3976 aopGet (AOP (right), offset, FALSE, TRUE),
3983 /* right is a pointer reg need both a & b */
3986 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3987 if (strcmp (l, "b"))
3988 emitcode ("mov", "b,%s", l);
3989 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3990 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3996 /*-----------------------------------------------------------------*/
3997 /* gencjne - compare and jump if not equal */
3998 /*-----------------------------------------------------------------*/
4000 gencjne (operand * left, operand * right, symbol * lbl)
4002 symbol *tlbl = newiTempLabel (NULL);
4004 gencjneshort (left, right, lbl);
4006 emitcode ("mov", "a,%s", one);
4007 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4008 emitcode ("", "%05d$:", lbl->key + 100);
4009 emitcode ("clr", "a");
4010 emitcode ("", "%05d$:", tlbl->key + 100);
4013 /*-----------------------------------------------------------------*/
4014 /* genCmpEq - generates code for equal to */
4015 /*-----------------------------------------------------------------*/
4017 genCmpEq (iCode * ic, iCode * ifx)
4019 operand *left, *right, *result;
4021 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4022 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4023 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4025 /* if literal, literal on the right or
4026 if the right is in a pointer register and left
4028 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4029 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4031 operand *t = IC_RIGHT (ic);
4032 IC_RIGHT (ic) = IC_LEFT (ic);
4036 if (ifx && !AOP_SIZE (result))
4039 /* if they are both bit variables */
4040 if (AOP_TYPE (left) == AOP_CRY &&
4041 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4043 if (AOP_TYPE (right) == AOP_LIT)
4045 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4048 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4049 emitcode ("cpl", "c");
4053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4057 emitcode ("clr", "c");
4059 /* AOP_TYPE(right) == AOP_CRY */
4063 symbol *lbl = newiTempLabel (NULL);
4064 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4065 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4066 emitcode ("cpl", "c");
4067 emitcode ("", "%05d$:", (lbl->key + 100));
4069 /* if true label then we jump if condition
4071 tlbl = newiTempLabel (NULL);
4074 emitcode ("jnc", "%05d$", tlbl->key + 100);
4075 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4079 emitcode ("jc", "%05d$", tlbl->key + 100);
4080 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4082 emitcode ("", "%05d$:", tlbl->key + 100);
4086 tlbl = newiTempLabel (NULL);
4087 gencjneshort (left, right, tlbl);
4090 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4091 emitcode ("", "%05d$:", tlbl->key + 100);
4095 symbol *lbl = newiTempLabel (NULL);
4096 emitcode ("sjmp", "%05d$", lbl->key + 100);
4097 emitcode ("", "%05d$:", tlbl->key + 100);
4098 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4099 emitcode ("", "%05d$:", lbl->key + 100);
4102 /* mark the icode as generated */
4107 /* if they are both bit variables */
4108 if (AOP_TYPE (left) == AOP_CRY &&
4109 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4111 if (AOP_TYPE (right) == AOP_LIT)
4113 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4116 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4117 emitcode ("cpl", "c");
4121 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4125 emitcode ("clr", "c");
4127 /* AOP_TYPE(right) == AOP_CRY */
4131 symbol *lbl = newiTempLabel (NULL);
4132 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4133 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4134 emitcode ("cpl", "c");
4135 emitcode ("", "%05d$:", (lbl->key + 100));
4138 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4145 genIfxJump (ifx, "c");
4148 /* if the result is used in an arithmetic operation
4149 then put the result in place */
4154 gencjne (left, right, newiTempLabel (NULL));
4155 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4157 aopPut (AOP (result), "a", 0);
4162 genIfxJump (ifx, "a");
4165 /* if the result is used in an arithmetic operation
4166 then put the result in place */
4167 if (AOP_TYPE (result) != AOP_CRY)
4169 /* leave the result in acc */
4173 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4174 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4175 freeAsmop (result, NULL, ic, TRUE);
4178 /*-----------------------------------------------------------------*/
4179 /* ifxForOp - returns the icode containing the ifx for operand */
4180 /*-----------------------------------------------------------------*/
4182 ifxForOp (operand * op, iCode * ic)
4184 /* if true symbol then needs to be assigned */
4185 if (IS_TRUE_SYMOP (op))
4188 /* if this has register type condition and
4189 the next instruction is ifx with the same operand
4190 and live to of the operand is upto the ifx only then */
4192 ic->next->op == IFX &&
4193 IC_COND (ic->next)->key == op->key &&
4194 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4200 /*-----------------------------------------------------------------*/
4201 /* hasInc - operand is incremented before any other use */
4202 /*-----------------------------------------------------------------*/
4204 hasInc (operand *op, iCode *ic)
4206 sym_link *type = operandType(op);
4207 sym_link *retype = getSpec (type);
4208 iCode *lic = ic->next;
4211 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4212 if (!IS_SYMOP(op)) return NULL;
4214 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4215 isize = getSize(type->next);
4217 /* if operand of the form op = op + <sizeof *op> */
4218 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4219 isOperandEqual(IC_RESULT(lic),op) &&
4220 isOperandLiteral(IC_RIGHT(lic)) &&
4221 operandLitValue(IC_RIGHT(lic)) == isize) {
4224 /* if the operand used or deffed */
4225 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4233 /*-----------------------------------------------------------------*/
4234 /* genAndOp - for && operation */
4235 /*-----------------------------------------------------------------*/
4237 genAndOp (iCode * ic)
4239 operand *left, *right, *result;
4242 /* note here that && operations that are in an
4243 if statement are taken away by backPatchLabels
4244 only those used in arthmetic operations remain */
4245 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4246 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4247 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4249 /* if both are bit variables */
4250 if (AOP_TYPE (left) == AOP_CRY &&
4251 AOP_TYPE (right) == AOP_CRY)
4253 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4254 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4259 tlbl = newiTempLabel (NULL);
4261 emitcode ("jz", "%05d$", tlbl->key + 100);
4263 emitcode ("", "%05d$:", tlbl->key + 100);
4267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (result, NULL, ic, TRUE);
4273 /*-----------------------------------------------------------------*/
4274 /* genOrOp - for || operation */
4275 /*-----------------------------------------------------------------*/
4277 genOrOp (iCode * ic)
4279 operand *left, *right, *result;
4282 /* note here that || operations that are in an
4283 if statement are taken away by backPatchLabels
4284 only those used in arthmetic operations remain */
4285 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4286 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4287 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4289 /* if both are bit variables */
4290 if (AOP_TYPE (left) == AOP_CRY &&
4291 AOP_TYPE (right) == AOP_CRY)
4293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4294 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4299 tlbl = newiTempLabel (NULL);
4301 emitcode ("jnz", "%05d$", tlbl->key + 100);
4303 emitcode ("", "%05d$:", tlbl->key + 100);
4307 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4308 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 freeAsmop (result, NULL, ic, TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* isLiteralBit - test if lit == 2^n */
4314 /*-----------------------------------------------------------------*/
4316 isLiteralBit (unsigned long lit)
4318 unsigned long pw[32] =
4319 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4320 0x100L, 0x200L, 0x400L, 0x800L,
4321 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4322 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4323 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4324 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4325 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4328 for (idx = 0; idx < 32; idx++)
4334 /*-----------------------------------------------------------------*/
4335 /* continueIfTrue - */
4336 /*-----------------------------------------------------------------*/
4338 continueIfTrue (iCode * ic)
4341 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4345 /*-----------------------------------------------------------------*/
4347 /*-----------------------------------------------------------------*/
4349 jumpIfTrue (iCode * ic)
4352 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4356 /*-----------------------------------------------------------------*/
4357 /* jmpTrueOrFalse - */
4358 /*-----------------------------------------------------------------*/
4360 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4362 // ugly but optimized by peephole
4365 symbol *nlbl = newiTempLabel (NULL);
4366 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4367 emitcode ("", "%05d$:", tlbl->key + 100);
4368 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4369 emitcode ("", "%05d$:", nlbl->key + 100);
4373 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4374 emitcode ("", "%05d$:", tlbl->key + 100);
4379 /*-----------------------------------------------------------------*/
4380 /* genAnd - code for and */
4381 /*-----------------------------------------------------------------*/
4383 genAnd (iCode * ic, iCode * ifx)
4385 operand *left, *right, *result;
4386 int size, offset = 0;
4387 unsigned long lit = 0L;
4391 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4392 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4393 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4396 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4398 AOP_TYPE (left), AOP_TYPE (right));
4399 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4401 AOP_SIZE (left), AOP_SIZE (right));
4404 /* if left is a literal & right is not then exchange them */
4405 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4406 AOP_NEEDSACC (left))
4408 operand *tmp = right;
4413 /* if result = right then exchange them */
4414 if (sameRegs (AOP (result), AOP (right)))
4416 operand *tmp = right;
4421 /* if right is bit then exchange them */
4422 if (AOP_TYPE (right) == AOP_CRY &&
4423 AOP_TYPE (left) != AOP_CRY)
4425 operand *tmp = right;
4429 if (AOP_TYPE (right) == AOP_LIT)
4430 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4432 size = AOP_SIZE (result);
4435 // result = bit & yy;
4436 if (AOP_TYPE (left) == AOP_CRY)
4438 // c = bit & literal;
4439 if (AOP_TYPE (right) == AOP_LIT)
4443 if (size && sameRegs (AOP (result), AOP (left)))
4446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4451 if (size && (AOP_TYPE (result) == AOP_CRY))
4453 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4456 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4461 emitcode ("clr", "c");
4466 if (AOP_TYPE (right) == AOP_CRY)
4469 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4470 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4475 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4477 emitcode ("rrc", "a");
4478 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4486 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4487 genIfxJump (ifx, "c");
4491 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4492 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4493 if ((AOP_TYPE (right) == AOP_LIT) &&
4494 (AOP_TYPE (result) == AOP_CRY) &&
4495 (AOP_TYPE (left) != AOP_CRY))
4497 int posbit = isLiteralBit (lit);
4502 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4505 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4511 sprintf (buffer, "acc.%d", posbit & 0x07);
4512 genIfxJump (ifx, buffer);
4519 symbol *tlbl = newiTempLabel (NULL);
4520 int sizel = AOP_SIZE (left);
4522 emitcode ("setb", "c");
4525 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4527 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4529 if ((posbit = isLiteralBit (bytelit)) != 0)
4530 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4533 if (bytelit != 0x0FFL)
4534 emitcode ("anl", "a,%s",
4535 aopGet (AOP (right), offset, FALSE, TRUE));
4536 emitcode ("jnz", "%05d$", tlbl->key + 100);
4541 // bit = left & literal
4544 emitcode ("clr", "c");
4545 emitcode ("", "%05d$:", tlbl->key + 100);
4547 // if(left & literal)
4551 jmpTrueOrFalse (ifx, tlbl);
4559 /* if left is same as result */
4560 if (sameRegs (AOP (result), AOP (left)))
4562 for (; size--; offset++)
4564 if (AOP_TYPE (right) == AOP_LIT)
4566 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4568 else if (bytelit == 0)
4569 aopPut (AOP (result), zero, offset);
4570 else if (IS_AOP_PREG (result))
4572 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4573 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4574 aopPut (AOP (result), "a", offset);
4577 emitcode ("anl", "%s,%s",
4578 aopGet (AOP (left), offset, FALSE, TRUE),
4579 aopGet (AOP (right), offset, FALSE, FALSE));
4583 if (AOP_TYPE (left) == AOP_ACC)
4584 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4587 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4588 if (IS_AOP_PREG (result))
4590 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4591 aopPut (AOP (result), "a", offset);
4595 emitcode ("anl", "%s,a",
4596 aopGet (AOP (left), offset, FALSE, TRUE));
4603 // left & result in different registers
4604 if (AOP_TYPE (result) == AOP_CRY)
4607 // if(size), result in bit
4608 // if(!size && ifx), conditional oper: if(left & right)
4609 symbol *tlbl = newiTempLabel (NULL);
4610 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4612 emitcode ("setb", "c");
4615 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4616 emitcode ("anl", "a,%s",
4617 aopGet (AOP (right), offset, FALSE, FALSE));
4619 if (AOP_TYPE(left)==AOP_ACC) {
4620 emitcode("mov", "b,a");
4621 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4622 emitcode("anl", "a,b");
4624 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4625 emitcode ("anl", "a,%s",
4626 aopGet (AOP (left), offset, FALSE, FALSE));
4629 emitcode ("jnz", "%05d$", tlbl->key + 100);
4635 emitcode ("", "%05d$:", tlbl->key + 100);
4639 jmpTrueOrFalse (ifx, tlbl);
4643 for (; (size--); offset++)
4646 // result = left & right
4647 if (AOP_TYPE (right) == AOP_LIT)
4649 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4651 aopPut (AOP (result),
4652 aopGet (AOP (left), offset, FALSE, FALSE),
4656 else if (bytelit == 0)
4658 aopPut (AOP (result), zero, offset);
4662 // faster than result <- left, anl result,right
4663 // and better if result is SFR
4664 if (AOP_TYPE (left) == AOP_ACC)
4665 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4668 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4669 emitcode ("anl", "a,%s",
4670 aopGet (AOP (left), offset, FALSE, FALSE));
4672 aopPut (AOP (result), "a", offset);
4678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (result, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* genOr - code for or */
4685 /*-----------------------------------------------------------------*/
4687 genOr (iCode * ic, iCode * ifx)
4689 operand *left, *right, *result;
4690 int size, offset = 0;
4691 unsigned long lit = 0L;
4693 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4694 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4695 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4698 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4700 AOP_TYPE (left), AOP_TYPE (right));
4701 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4703 AOP_SIZE (left), AOP_SIZE (right));
4706 /* if left is a literal & right is not then exchange them */
4707 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4708 AOP_NEEDSACC (left))
4710 operand *tmp = right;
4715 /* if result = right then exchange them */
4716 if (sameRegs (AOP (result), AOP (right)))
4718 operand *tmp = right;
4723 /* if right is bit then exchange them */
4724 if (AOP_TYPE (right) == AOP_CRY &&
4725 AOP_TYPE (left) != AOP_CRY)
4727 operand *tmp = right;
4731 if (AOP_TYPE (right) == AOP_LIT)
4732 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4734 size = AOP_SIZE (result);
4738 if (AOP_TYPE (left) == AOP_CRY)
4740 if (AOP_TYPE (right) == AOP_LIT)
4742 // c = bit & literal;
4745 // lit != 0 => result = 1
4746 if (AOP_TYPE (result) == AOP_CRY)
4749 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4751 continueIfTrue (ifx);
4754 emitcode ("setb", "c");
4758 // lit == 0 => result = left
4759 if (size && sameRegs (AOP (result), AOP (left)))
4761 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4766 if (AOP_TYPE (right) == AOP_CRY)
4769 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4770 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4775 symbol *tlbl = newiTempLabel (NULL);
4776 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4777 emitcode ("setb", "c");
4778 emitcode ("jb", "%s,%05d$",
4779 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4781 emitcode ("jnz", "%05d$", tlbl->key + 100);
4782 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4784 jmpTrueOrFalse (ifx, tlbl);
4790 emitcode ("", "%05d$:", tlbl->key + 100);
4799 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4800 genIfxJump (ifx, "c");
4804 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4805 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4806 if ((AOP_TYPE (right) == AOP_LIT) &&
4807 (AOP_TYPE (result) == AOP_CRY) &&
4808 (AOP_TYPE (left) != AOP_CRY))
4814 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4816 continueIfTrue (ifx);
4821 // lit = 0, result = boolean(left)
4823 emitcode ("setb", "c");
4827 symbol *tlbl = newiTempLabel (NULL);
4828 emitcode ("jnz", "%05d$", tlbl->key + 100);
4830 emitcode ("", "%05d$:", tlbl->key + 100);
4834 genIfxJump (ifx, "a");
4842 /* if left is same as result */
4843 if (sameRegs (AOP (result), AOP (left)))
4845 for (; size--; offset++)
4847 if (AOP_TYPE (right) == AOP_LIT)
4849 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4851 else if (IS_AOP_PREG (left))
4853 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4854 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4855 aopPut (AOP (result), "a", offset);
4858 emitcode ("orl", "%s,%s",
4859 aopGet (AOP (left), offset, FALSE, TRUE),
4860 aopGet (AOP (right), offset, FALSE, FALSE));
4864 if (AOP_TYPE (left) == AOP_ACC)
4865 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4868 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4869 if (IS_AOP_PREG (left))
4871 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4872 aopPut (AOP (result), "a", offset);
4875 emitcode ("orl", "%s,a",
4876 aopGet (AOP (left), offset, FALSE, TRUE));
4883 // left & result in different registers
4884 if (AOP_TYPE (result) == AOP_CRY)
4887 // if(size), result in bit
4888 // if(!size && ifx), conditional oper: if(left | right)
4889 symbol *tlbl = newiTempLabel (NULL);
4890 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4892 emitcode ("setb", "c");
4895 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4896 emitcode ("orl", "a,%s",
4897 aopGet (AOP (right), offset, FALSE, FALSE));
4899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4900 emitcode ("orl", "a,%s",
4901 aopGet (AOP (left), offset, FALSE, FALSE));
4903 emitcode ("jnz", "%05d$", tlbl->key + 100);
4909 emitcode ("", "%05d$:", tlbl->key + 100);
4913 jmpTrueOrFalse (ifx, tlbl);
4916 for (; (size--); offset++)
4919 // result = left & right
4920 if (AOP_TYPE (right) == AOP_LIT)
4922 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4924 aopPut (AOP (result),
4925 aopGet (AOP (left), offset, FALSE, FALSE),
4930 // faster than result <- left, anl result,right
4931 // and better if result is SFR
4932 if (AOP_TYPE (left) == AOP_ACC)
4933 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4936 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4937 emitcode ("orl", "a,%s",
4938 aopGet (AOP (left), offset, FALSE, FALSE));
4940 aopPut (AOP (result), "a", offset);
4945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947 freeAsmop (result, NULL, ic, TRUE);
4950 /*-----------------------------------------------------------------*/
4951 /* genXor - code for xclusive or */
4952 /*-----------------------------------------------------------------*/
4954 genXor (iCode * ic, iCode * ifx)
4956 operand *left, *right, *result;
4957 int size, offset = 0;
4958 unsigned long lit = 0L;
4960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4965 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4967 AOP_TYPE (left), AOP_TYPE (right));
4968 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4970 AOP_SIZE (left), AOP_SIZE (right));
4973 /* if left is a literal & right is not ||
4974 if left needs acc & right does not */
4975 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4976 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4978 operand *tmp = right;
4983 /* if result = right then exchange them */
4984 if (sameRegs (AOP (result), AOP (right)))
4986 operand *tmp = right;
4991 /* if right is bit then exchange them */
4992 if (AOP_TYPE (right) == AOP_CRY &&
4993 AOP_TYPE (left) != AOP_CRY)
4995 operand *tmp = right;
4999 if (AOP_TYPE (right) == AOP_LIT)
5000 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5002 size = AOP_SIZE (result);
5006 if (AOP_TYPE (left) == AOP_CRY)
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 // c = bit & literal;
5013 // lit>>1 != 0 => result = 1
5014 if (AOP_TYPE (result) == AOP_CRY)
5017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5019 continueIfTrue (ifx);
5022 emitcode ("setb", "c");
5029 // lit == 0, result = left
5030 if (size && sameRegs (AOP (result), AOP (left)))
5032 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5036 // lit == 1, result = not(left)
5037 if (size && sameRegs (AOP (result), AOP (left)))
5039 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5045 emitcode ("cpl", "c");
5054 symbol *tlbl = newiTempLabel (NULL);
5055 if (AOP_TYPE (right) == AOP_CRY)
5058 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5062 int sizer = AOP_SIZE (right);
5064 // if val>>1 != 0, result = 1
5065 emitcode ("setb", "c");
5068 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5070 // test the msb of the lsb
5071 emitcode ("anl", "a,#0xfe");
5072 emitcode ("jnz", "%05d$", tlbl->key + 100);
5076 emitcode ("rrc", "a");
5078 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5079 emitcode ("cpl", "c");
5080 emitcode ("", "%05d$:", (tlbl->key + 100));
5087 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5088 genIfxJump (ifx, "c");
5092 if (sameRegs (AOP (result), AOP (left)))
5094 /* if left is same as result */
5095 for (; size--; offset++)
5097 if (AOP_TYPE (right) == AOP_LIT)
5099 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5101 else if (IS_AOP_PREG (left))
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5104 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5105 aopPut (AOP (result), "a", offset);
5108 emitcode ("xrl", "%s,%s",
5109 aopGet (AOP (left), offset, FALSE, TRUE),
5110 aopGet (AOP (right), offset, FALSE, FALSE));
5114 if (AOP_TYPE (left) == AOP_ACC)
5115 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5119 if (IS_AOP_PREG (left))
5121 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5122 aopPut (AOP (result), "a", offset);
5125 emitcode ("xrl", "%s,a",
5126 aopGet (AOP (left), offset, FALSE, TRUE));
5133 // left & result in different registers
5134 if (AOP_TYPE (result) == AOP_CRY)
5137 // if(size), result in bit
5138 // if(!size && ifx), conditional oper: if(left ^ right)
5139 symbol *tlbl = newiTempLabel (NULL);
5140 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5142 emitcode ("setb", "c");
5145 if ((AOP_TYPE (right) == AOP_LIT) &&
5146 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5148 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5152 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5153 emitcode ("xrl", "a,%s",
5154 aopGet (AOP (right), offset, FALSE, FALSE));
5156 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5157 emitcode ("xrl", "a,%s",
5158 aopGet (AOP (left), offset, FALSE, FALSE));
5161 emitcode ("jnz", "%05d$", tlbl->key + 100);
5167 emitcode ("", "%05d$:", tlbl->key + 100);
5171 jmpTrueOrFalse (ifx, tlbl);
5174 for (; (size--); offset++)
5177 // result = left & right
5178 if (AOP_TYPE (right) == AOP_LIT)
5180 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5182 aopPut (AOP (result),
5183 aopGet (AOP (left), offset, FALSE, FALSE),
5188 // faster than result <- left, anl result,right
5189 // and better if result is SFR
5190 if (AOP_TYPE (left) == AOP_ACC)
5191 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5194 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5195 emitcode ("xrl", "a,%s",
5196 aopGet (AOP (left), offset, FALSE, TRUE));
5198 aopPut (AOP (result), "a", offset);
5203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 freeAsmop (result, NULL, ic, TRUE);
5208 /*-----------------------------------------------------------------*/
5209 /* genInline - write the inline code out */
5210 /*-----------------------------------------------------------------*/
5212 genInline (iCode * ic)
5214 char *buffer, *bp, *bp1;
5216 _G.inLine += (!options.asmpeep);
5218 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5219 strcpy (buffer, IC_INLINE (ic));
5221 /* emit each line as a code */
5246 /* emitcode("",buffer); */
5247 _G.inLine -= (!options.asmpeep);
5250 /*-----------------------------------------------------------------*/
5251 /* genRRC - rotate right with carry */
5252 /*-----------------------------------------------------------------*/
5256 operand *left, *result;
5257 int size, offset = 0;
5260 /* rotate right with carry */
5261 left = IC_LEFT (ic);
5262 result = IC_RESULT (ic);
5263 aopOp (left, ic, FALSE);
5264 aopOp (result, ic, FALSE);
5266 /* move it to the result */
5267 size = AOP_SIZE (result);
5269 if (size == 1) { /* special case for 1 byte */
5270 l = aopGet (AOP (left), offset, FALSE, FALSE);
5272 emitcode ("rr", "a");
5278 l = aopGet (AOP (left), offset, FALSE, FALSE);
5280 emitcode ("rrc", "a");
5281 if (AOP_SIZE (result) > 1)
5282 aopPut (AOP (result), "a", offset--);
5284 /* now we need to put the carry into the
5285 highest order byte of the result */
5286 if (AOP_SIZE (result) > 1)
5288 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5291 emitcode ("mov", "acc.7,c");
5293 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5294 freeAsmop (left, NULL, ic, TRUE);
5295 freeAsmop (result, NULL, ic, TRUE);
5298 /*-----------------------------------------------------------------*/
5299 /* genRLC - generate code for rotate left with carry */
5300 /*-----------------------------------------------------------------*/
5304 operand *left, *result;
5305 int size, offset = 0;
5308 /* rotate right with carry */
5309 left = IC_LEFT (ic);
5310 result = IC_RESULT (ic);
5311 aopOp (left, ic, FALSE);
5312 aopOp (result, ic, FALSE);
5314 /* move it to the result */
5315 size = AOP_SIZE (result);
5319 l = aopGet (AOP (left), offset, FALSE, FALSE);
5321 if (size == 0) { /* special case for 1 byte */
5325 emitcode ("add", "a,acc");
5326 if (AOP_SIZE (result) > 1)
5327 aopPut (AOP (result), "a", offset++);
5330 l = aopGet (AOP (left), offset, FALSE, FALSE);
5332 emitcode ("rlc", "a");
5333 if (AOP_SIZE (result) > 1)
5334 aopPut (AOP (result), "a", offset++);
5337 /* now we need to put the carry into the
5338 highest order byte of the result */
5339 if (AOP_SIZE (result) > 1)
5341 l = aopGet (AOP (result), 0, FALSE, FALSE);
5344 emitcode ("mov", "acc.0,c");
5346 aopPut (AOP (result), "a", 0);
5347 freeAsmop (left, NULL, ic, TRUE);
5348 freeAsmop (result, NULL, ic, TRUE);
5351 /*-----------------------------------------------------------------*/
5352 /* genGetHbit - generates code get highest order bit */
5353 /*-----------------------------------------------------------------*/
5355 genGetHbit (iCode * ic)
5357 operand *left, *result;
5358 left = IC_LEFT (ic);
5359 result = IC_RESULT (ic);
5360 aopOp (left, ic, FALSE);
5361 aopOp (result, ic, FALSE);
5363 /* get the highest order byte into a */
5364 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5365 if (AOP_TYPE (result) == AOP_CRY)
5367 emitcode ("rlc", "a");
5372 emitcode ("rl", "a");
5373 emitcode ("anl", "a,#0x01");
5378 freeAsmop (left, NULL, ic, TRUE);
5379 freeAsmop (result, NULL, ic, TRUE);
5382 /*-----------------------------------------------------------------*/
5383 /* AccRol - rotate left accumulator by known count */
5384 /*-----------------------------------------------------------------*/
5386 AccRol (int shCount)
5388 shCount &= 0x0007; // shCount : 0..7
5395 emitcode ("rl", "a");
5398 emitcode ("rl", "a");
5399 emitcode ("rl", "a");
5402 emitcode ("swap", "a");
5403 emitcode ("rr", "a");
5406 emitcode ("swap", "a");
5409 emitcode ("swap", "a");
5410 emitcode ("rl", "a");
5413 emitcode ("rr", "a");
5414 emitcode ("rr", "a");
5417 emitcode ("rr", "a");
5422 /*-----------------------------------------------------------------*/
5423 /* AccLsh - left shift accumulator by known count */
5424 /*-----------------------------------------------------------------*/
5426 AccLsh (int shCount)
5431 emitcode ("add", "a,acc");
5432 else if (shCount == 2)
5434 emitcode ("add", "a,acc");
5435 emitcode ("add", "a,acc");
5439 /* rotate left accumulator */
5441 /* and kill the lower order bits */
5442 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5447 /*-----------------------------------------------------------------*/
5448 /* AccRsh - right shift accumulator by known count */
5449 /*-----------------------------------------------------------------*/
5451 AccRsh (int shCount)
5458 emitcode ("rrc", "a");
5462 /* rotate right accumulator */
5463 AccRol (8 - shCount);
5464 /* and kill the higher order bits */
5465 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5470 /*-----------------------------------------------------------------*/
5471 /* AccSRsh - signed right shift accumulator by known count */
5472 /*-----------------------------------------------------------------*/
5474 AccSRsh (int shCount)
5481 emitcode ("mov", "c,acc.7");
5482 emitcode ("rrc", "a");
5484 else if (shCount == 2)
5486 emitcode ("mov", "c,acc.7");
5487 emitcode ("rrc", "a");
5488 emitcode ("mov", "c,acc.7");
5489 emitcode ("rrc", "a");
5493 tlbl = newiTempLabel (NULL);
5494 /* rotate right accumulator */
5495 AccRol (8 - shCount);
5496 /* and kill the higher order bits */
5497 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5498 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5499 emitcode ("orl", "a,#0x%02x",
5500 (unsigned char) ~SRMask[shCount]);
5501 emitcode ("", "%05d$:", tlbl->key + 100);
5506 /*-----------------------------------------------------------------*/
5507 /* shiftR1Left2Result - shift right one byte from left to result */
5508 /*-----------------------------------------------------------------*/
5510 shiftR1Left2Result (operand * left, int offl,
5511 operand * result, int offr,
5512 int shCount, int sign)
5514 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5515 /* shift right accumulator */
5520 aopPut (AOP (result), "a", offr);
5523 /*-----------------------------------------------------------------*/
5524 /* shiftL1Left2Result - shift left one byte from left to result */
5525 /*-----------------------------------------------------------------*/
5527 shiftL1Left2Result (operand * left, int offl,
5528 operand * result, int offr, int shCount)
5531 l = aopGet (AOP (left), offl, FALSE, FALSE);
5533 /* shift left accumulator */
5535 aopPut (AOP (result), "a", offr);
5538 /*-----------------------------------------------------------------*/
5539 /* movLeft2Result - move byte from left to result */
5540 /*-----------------------------------------------------------------*/
5542 movLeft2Result (operand * left, int offl,
5543 operand * result, int offr, int sign)
5546 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5548 l = aopGet (AOP (left), offl, FALSE, FALSE);
5550 if (*l == '@' && (IS_AOP_PREG (result)))
5552 emitcode ("mov", "a,%s", l);
5553 aopPut (AOP (result), "a", offr);
5558 aopPut (AOP (result), l, offr);
5561 /* MSB sign in acc.7 ! */
5562 if (getDataSize (left) == offl + 1)
5564 emitcode ("mov", "a,%s", l);
5565 aopPut (AOP (result), "a", offr);
5572 /*-----------------------------------------------------------------*/
5573 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5574 /*-----------------------------------------------------------------*/
5578 emitcode ("rrc", "a");
5579 emitcode ("xch", "a,%s", x);
5580 emitcode ("rrc", "a");
5581 emitcode ("xch", "a,%s", x);
5584 /*-----------------------------------------------------------------*/
5585 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5586 /*-----------------------------------------------------------------*/
5590 emitcode ("xch", "a,%s", x);
5591 emitcode ("rlc", "a");
5592 emitcode ("xch", "a,%s", x);
5593 emitcode ("rlc", "a");
5596 /*-----------------------------------------------------------------*/
5597 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5598 /*-----------------------------------------------------------------*/
5602 emitcode ("xch", "a,%s", x);
5603 emitcode ("add", "a,acc");
5604 emitcode ("xch", "a,%s", x);
5605 emitcode ("rlc", "a");
5608 /*-----------------------------------------------------------------*/
5609 /* AccAXLsh - left shift a:x by known count (0..7) */
5610 /*-----------------------------------------------------------------*/
5612 AccAXLsh (char *x, int shCount)
5627 case 5: // AAAAABBB:CCCCCDDD
5629 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5631 emitcode ("anl", "a,#0x%02x",
5632 SLMask[shCount]); // BBB00000:CCCCCDDD
5634 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5636 AccRol (shCount); // DDDCCCCC:BBB00000
5638 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5640 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5642 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5644 emitcode ("anl", "a,#0x%02x",
5645 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5647 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5649 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5652 case 6: // AAAAAABB:CCCCCCDD
5653 emitcode ("anl", "a,#0x%02x",
5654 SRMask[shCount]); // 000000BB:CCCCCCDD
5655 emitcode ("mov", "c,acc.0"); // c = B
5656 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5658 AccAXRrl1 (x); // BCCCCCCD:D000000B
5659 AccAXRrl1 (x); // BBCCCCCC:DD000000
5661 emitcode("rrc","a");
5662 emitcode("xch","a,%s", x);
5663 emitcode("rrc","a");
5664 emitcode("mov","c,acc.0"); //<< get correct bit
5665 emitcode("xch","a,%s", x);
5667 emitcode("rrc","a");
5668 emitcode("xch","a,%s", x);
5669 emitcode("rrc","a");
5670 emitcode("xch","a,%s", x);
5673 case 7: // a:x <<= 7
5675 emitcode ("anl", "a,#0x%02x",
5676 SRMask[shCount]); // 0000000B:CCCCCCCD
5678 emitcode ("mov", "c,acc.0"); // c = B
5680 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5682 AccAXRrl1 (x); // BCCCCCCC:D0000000
5690 /*-----------------------------------------------------------------*/
5691 /* AccAXRsh - right shift a:x known count (0..7) */
5692 /*-----------------------------------------------------------------*/
5694 AccAXRsh (char *x, int shCount)
5702 AccAXRrl1 (x); // 0->a:x
5707 AccAXRrl1 (x); // 0->a:x
5710 AccAXRrl1 (x); // 0->a:x
5715 case 5: // AAAAABBB:CCCCCDDD = a:x
5717 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5719 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5721 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5723 emitcode ("anl", "a,#0x%02x",
5724 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5726 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5728 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5730 emitcode ("anl", "a,#0x%02x",
5731 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5733 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5735 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5737 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5740 case 6: // AABBBBBB:CCDDDDDD
5742 emitcode ("mov", "c,acc.7");
5743 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5745 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5747 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5749 emitcode ("anl", "a,#0x%02x",
5750 SRMask[shCount]); // 000000AA:BBBBBBCC
5753 case 7: // ABBBBBBB:CDDDDDDD
5755 emitcode ("mov", "c,acc.7"); // c = A
5757 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5759 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5761 emitcode ("anl", "a,#0x%02x",
5762 SRMask[shCount]); // 0000000A:BBBBBBBC
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXRshS - right shift signed a:x known count (0..7) */
5772 /*-----------------------------------------------------------------*/
5774 AccAXRshS (char *x, int shCount)
5782 emitcode ("mov", "c,acc.7");
5783 AccAXRrl1 (x); // s->a:x
5787 emitcode ("mov", "c,acc.7");
5788 AccAXRrl1 (x); // s->a:x
5790 emitcode ("mov", "c,acc.7");
5791 AccAXRrl1 (x); // s->a:x
5796 case 5: // AAAAABBB:CCCCCDDD = a:x
5798 tlbl = newiTempLabel (NULL);
5799 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5801 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5803 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5805 emitcode ("anl", "a,#0x%02x",
5806 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5808 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5810 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5812 emitcode ("anl", "a,#0x%02x",
5813 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5815 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5817 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5819 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5821 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5822 emitcode ("orl", "a,#0x%02x",
5823 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5825 emitcode ("", "%05d$:", tlbl->key + 100);
5826 break; // SSSSAAAA:BBBCCCCC
5828 case 6: // AABBBBBB:CCDDDDDD
5830 tlbl = newiTempLabel (NULL);
5831 emitcode ("mov", "c,acc.7");
5832 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5834 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5836 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5838 emitcode ("anl", "a,#0x%02x",
5839 SRMask[shCount]); // 000000AA:BBBBBBCC
5841 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5842 emitcode ("orl", "a,#0x%02x",
5843 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5845 emitcode ("", "%05d$:", tlbl->key + 100);
5847 case 7: // ABBBBBBB:CDDDDDDD
5849 tlbl = newiTempLabel (NULL);
5850 emitcode ("mov", "c,acc.7"); // c = A
5852 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5854 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5856 emitcode ("anl", "a,#0x%02x",
5857 SRMask[shCount]); // 0000000A:BBBBBBBC
5859 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5860 emitcode ("orl", "a,#0x%02x",
5861 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5863 emitcode ("", "%05d$:", tlbl->key + 100);
5870 /*-----------------------------------------------------------------*/
5871 /* shiftL2Left2Result - shift left two bytes from left to result */
5872 /*-----------------------------------------------------------------*/
5874 shiftL2Left2Result (operand * left, int offl,
5875 operand * result, int offr, int shCount)
5877 if (sameRegs (AOP (result), AOP (left)) &&
5878 ((offl + MSB16) == offr))
5880 /* don't crash result[offr] */
5881 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5882 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5886 movLeft2Result (left, offl, result, offr, 0);
5887 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5889 /* ax << shCount (x = lsb(result)) */
5890 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5891 aopPut (AOP (result), "a", offr + MSB16);
5895 /*-----------------------------------------------------------------*/
5896 /* shiftR2Left2Result - shift right two bytes from left to result */
5897 /*-----------------------------------------------------------------*/
5899 shiftR2Left2Result (operand * left, int offl,
5900 operand * result, int offr,
5901 int shCount, int sign)
5903 if (sameRegs (AOP (result), AOP (left)) &&
5904 ((offl + MSB16) == offr))
5906 /* don't crash result[offr] */
5907 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5908 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5912 movLeft2Result (left, offl, result, offr, 0);
5913 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5915 /* a:x >> shCount (x = lsb(result)) */
5917 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5919 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5920 if (getDataSize (result) > 1)
5921 aopPut (AOP (result), "a", offr + MSB16);
5924 /*-----------------------------------------------------------------*/
5925 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5926 /*-----------------------------------------------------------------*/
5928 shiftLLeftOrResult (operand * left, int offl,
5929 operand * result, int offr, int shCount)
5931 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5932 /* shift left accumulator */
5934 /* or with result */
5935 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5936 /* back to result */
5937 aopPut (AOP (result), "a", offr);
5940 /*-----------------------------------------------------------------*/
5941 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5942 /*-----------------------------------------------------------------*/
5944 shiftRLeftOrResult (operand * left, int offl,
5945 operand * result, int offr, int shCount)
5947 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5948 /* shift right accumulator */
5950 /* or with result */
5951 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5952 /* back to result */
5953 aopPut (AOP (result), "a", offr);
5956 /*-----------------------------------------------------------------*/
5957 /* genlshOne - left shift a one byte quantity by known count */
5958 /*-----------------------------------------------------------------*/
5960 genlshOne (operand * result, operand * left, int shCount)
5962 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5965 /*-----------------------------------------------------------------*/
5966 /* genlshTwo - left shift two bytes by known amount != 0 */
5967 /*-----------------------------------------------------------------*/
5969 genlshTwo (operand * result, operand * left, int shCount)
5973 size = getDataSize (result);
5975 /* if shCount >= 8 */
5983 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5985 movLeft2Result (left, LSB, result, MSB16, 0);
5987 aopPut (AOP (result), zero, LSB);
5990 /* 1 <= shCount <= 7 */
5994 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5996 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6000 /*-----------------------------------------------------------------*/
6001 /* shiftLLong - shift left one long from left to result */
6002 /* offl = LSB or MSB16 */
6003 /*-----------------------------------------------------------------*/
6005 shiftLLong (operand * left, operand * result, int offr)
6008 int size = AOP_SIZE (result);
6010 if (size >= LSB + offr)
6012 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6014 emitcode ("add", "a,acc");
6015 if (sameRegs (AOP (left), AOP (result)) &&
6016 size >= MSB16 + offr && offr != LSB)
6017 emitcode ("xch", "a,%s",
6018 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6020 aopPut (AOP (result), "a", LSB + offr);
6023 if (size >= MSB16 + offr)
6025 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6027 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6030 emitcode ("rlc", "a");
6031 if (sameRegs (AOP (left), AOP (result)) &&
6032 size >= MSB24 + offr && offr != LSB)
6033 emitcode ("xch", "a,%s",
6034 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6036 aopPut (AOP (result), "a", MSB16 + offr);
6039 if (size >= MSB24 + offr)
6041 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6043 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6046 emitcode ("rlc", "a");
6047 if (sameRegs (AOP (left), AOP (result)) &&
6048 size >= MSB32 + offr && offr != LSB)
6049 emitcode ("xch", "a,%s",
6050 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6052 aopPut (AOP (result), "a", MSB24 + offr);
6055 if (size > MSB32 + offr)
6057 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6059 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6062 emitcode ("rlc", "a");
6063 aopPut (AOP (result), "a", MSB32 + offr);
6066 aopPut (AOP (result), zero, LSB);
6069 /*-----------------------------------------------------------------*/
6070 /* genlshFour - shift four byte by a known amount != 0 */
6071 /*-----------------------------------------------------------------*/
6073 genlshFour (operand * result, operand * left, int shCount)
6077 size = AOP_SIZE (result);
6079 /* if shifting more that 3 bytes */
6084 /* lowest order of left goes to the highest
6085 order of the destination */
6086 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6088 movLeft2Result (left, LSB, result, MSB32, 0);
6089 aopPut (AOP (result), zero, LSB);
6090 aopPut (AOP (result), zero, MSB16);
6091 aopPut (AOP (result), zero, MSB24);
6095 /* more than two bytes */
6096 else if (shCount >= 16)
6098 /* lower order two bytes goes to higher order two bytes */
6100 /* if some more remaining */
6102 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6105 movLeft2Result (left, MSB16, result, MSB32, 0);
6106 movLeft2Result (left, LSB, result, MSB24, 0);
6108 aopPut (AOP (result), zero, MSB16);
6109 aopPut (AOP (result), zero, LSB);
6113 /* if more than 1 byte */
6114 else if (shCount >= 8)
6116 /* lower order three bytes goes to higher order three bytes */
6121 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6123 movLeft2Result (left, LSB, result, MSB16, 0);
6129 movLeft2Result (left, MSB24, result, MSB32, 0);
6130 movLeft2Result (left, MSB16, result, MSB24, 0);
6131 movLeft2Result (left, LSB, result, MSB16, 0);
6132 aopPut (AOP (result), zero, LSB);
6134 else if (shCount == 1)
6135 shiftLLong (left, result, MSB16);
6138 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6139 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6140 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6141 aopPut (AOP (result), zero, LSB);
6146 /* 1 <= shCount <= 7 */
6147 else if (shCount <= 2)
6149 shiftLLong (left, result, LSB);
6151 shiftLLong (result, result, LSB);
6153 /* 3 <= shCount <= 7, optimize */
6156 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6157 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6158 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6162 /*-----------------------------------------------------------------*/
6163 /* genLeftShiftLiteral - left shifting by known count */
6164 /*-----------------------------------------------------------------*/
6166 genLeftShiftLiteral (operand * left,
6171 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6174 freeAsmop (right, NULL, ic, TRUE);
6176 aopOp (left, ic, FALSE);
6177 aopOp (result, ic, FALSE);
6179 size = getSize (operandType (result));
6182 emitcode ("; shift left ", "result %d, left %d", size,
6186 /* I suppose that the left size >= result size */
6191 movLeft2Result (left, size, result, size, 0);
6195 else if (shCount >= (size * 8))
6197 aopPut (AOP (result), zero, size);
6203 genlshOne (result, left, shCount);
6207 genlshTwo (result, left, shCount);
6211 genlshFour (result, left, shCount);
6214 fprintf(stderr, "*** ack! mystery literal shift!\n");
6218 freeAsmop (left, NULL, ic, TRUE);
6219 freeAsmop (result, NULL, ic, TRUE);
6222 /*-----------------------------------------------------------------*/
6223 /* genLeftShift - generates code for left shifting */
6224 /*-----------------------------------------------------------------*/
6226 genLeftShift (iCode * ic)
6228 operand *left, *right, *result;
6231 symbol *tlbl, *tlbl1;
6233 right = IC_RIGHT (ic);
6234 left = IC_LEFT (ic);
6235 result = IC_RESULT (ic);
6237 aopOp (right, ic, FALSE);
6239 /* if the shift count is known then do it
6240 as efficiently as possible */
6241 if (AOP_TYPE (right) == AOP_LIT)
6243 genLeftShiftLiteral (left, right, result, ic);
6247 /* shift count is unknown then we have to form
6248 a loop get the loop count in B : Note: we take
6249 only the lower order byte since shifting
6250 more that 32 bits make no sense anyway, ( the
6251 largest size of an object can be only 32 bits ) */
6253 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6254 emitcode ("inc", "b");
6255 freeAsmop (right, NULL, ic, TRUE);
6256 aopOp (left, ic, FALSE);
6257 aopOp (result, ic, FALSE);
6259 /* now move the left to the result if they are not the
6261 if (!sameRegs (AOP (left), AOP (result)) &&
6262 AOP_SIZE (result) > 1)
6265 size = AOP_SIZE (result);
6269 l = aopGet (AOP (left), offset, FALSE, TRUE);
6270 if (*l == '@' && (IS_AOP_PREG (result)))
6273 emitcode ("mov", "a,%s", l);
6274 aopPut (AOP (result), "a", offset);
6277 aopPut (AOP (result), l, offset);
6282 tlbl = newiTempLabel (NULL);
6283 size = AOP_SIZE (result);
6285 tlbl1 = newiTempLabel (NULL);
6287 /* if it is only one byte then */
6290 symbol *tlbl1 = newiTempLabel (NULL);
6292 l = aopGet (AOP (left), 0, FALSE, FALSE);
6294 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6295 emitcode ("", "%05d$:", tlbl->key + 100);
6296 emitcode ("add", "a,acc");
6297 emitcode ("", "%05d$:", tlbl1->key + 100);
6298 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6299 aopPut (AOP (result), "a", 0);
6303 reAdjustPreg (AOP (result));
6305 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6306 emitcode ("", "%05d$:", tlbl->key + 100);
6307 l = aopGet (AOP (result), offset, FALSE, FALSE);
6309 emitcode ("add", "a,acc");
6310 aopPut (AOP (result), "a", offset++);
6313 l = aopGet (AOP (result), offset, FALSE, FALSE);
6315 emitcode ("rlc", "a");
6316 aopPut (AOP (result), "a", offset++);
6318 reAdjustPreg (AOP (result));
6320 emitcode ("", "%05d$:", tlbl1->key + 100);
6321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6323 freeAsmop (left, NULL, ic, TRUE);
6324 freeAsmop (result, NULL, ic, TRUE);
6327 /*-----------------------------------------------------------------*/
6328 /* genrshOne - right shift a one byte quantity by known count */
6329 /*-----------------------------------------------------------------*/
6331 genrshOne (operand * result, operand * left,
6332 int shCount, int sign)
6334 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6337 /*-----------------------------------------------------------------*/
6338 /* genrshTwo - right shift two bytes by known amount != 0 */
6339 /*-----------------------------------------------------------------*/
6341 genrshTwo (operand * result, operand * left,
6342 int shCount, int sign)
6344 /* if shCount >= 8 */
6349 shiftR1Left2Result (left, MSB16, result, LSB,
6352 movLeft2Result (left, MSB16, result, LSB, sign);
6353 addSign (result, MSB16, sign);
6356 /* 1 <= shCount <= 7 */
6358 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6361 /*-----------------------------------------------------------------*/
6362 /* shiftRLong - shift right one long from left to result */
6363 /* offl = LSB or MSB16 */
6364 /*-----------------------------------------------------------------*/
6366 shiftRLong (operand * left, int offl,
6367 operand * result, int sign)
6369 int isSameRegs=sameRegs(AOP(left),AOP(result));
6371 if (isSameRegs && offl>1) {
6372 // we are in big trouble, but this shouldn't happen
6373 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6376 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6381 emitcode ("rlc", "a");
6382 emitcode ("subb", "a,acc");
6383 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6385 aopPut (AOP(result), zero, MSB32);
6390 emitcode ("clr", "c");
6392 emitcode ("mov", "c,acc.7");
6395 emitcode ("rrc", "a");
6397 if (isSameRegs && offl==MSB16) {
6398 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6400 aopPut (AOP (result), "a", MSB32);
6401 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6404 emitcode ("rrc", "a");
6405 if (isSameRegs && offl==1) {
6406 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6408 aopPut (AOP (result), "a", MSB24);
6409 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6411 emitcode ("rrc", "a");
6412 aopPut (AOP (result), "a", MSB16 - offl);
6416 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6417 emitcode ("rrc", "a");
6418 aopPut (AOP (result), "a", LSB);
6422 /*-----------------------------------------------------------------*/
6423 /* genrshFour - shift four byte by a known amount != 0 */
6424 /*-----------------------------------------------------------------*/
6426 genrshFour (operand * result, operand * left,
6427 int shCount, int sign)
6429 /* if shifting more that 3 bytes */
6434 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6436 movLeft2Result (left, MSB32, result, LSB, sign);
6437 addSign (result, MSB16, sign);
6439 else if (shCount >= 16)
6443 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6446 movLeft2Result (left, MSB24, result, LSB, 0);
6447 movLeft2Result (left, MSB32, result, MSB16, sign);
6449 addSign (result, MSB24, sign);
6451 else if (shCount >= 8)
6455 shiftRLong (left, MSB16, result, sign);
6456 else if (shCount == 0)
6458 movLeft2Result (left, MSB16, result, LSB, 0);
6459 movLeft2Result (left, MSB24, result, MSB16, 0);
6460 movLeft2Result (left, MSB32, result, MSB24, sign);
6461 addSign (result, MSB32, sign);
6465 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6466 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6467 /* the last shift is signed */
6468 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6469 addSign (result, MSB32, sign);
6473 { /* 1 <= shCount <= 7 */
6476 shiftRLong (left, LSB, result, sign);
6478 shiftRLong (result, LSB, result, sign);
6482 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6483 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6484 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6489 /*-----------------------------------------------------------------*/
6490 /* genRightShiftLiteral - right shifting by known count */
6491 /*-----------------------------------------------------------------*/
6493 genRightShiftLiteral (operand * left,
6499 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6502 freeAsmop (right, NULL, ic, TRUE);
6504 aopOp (left, ic, FALSE);
6505 aopOp (result, ic, FALSE);
6508 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6512 size = getDataSize (left);
6513 /* test the LEFT size !!! */
6515 /* I suppose that the left size >= result size */
6518 size = getDataSize (result);
6520 movLeft2Result (left, size, result, size, 0);
6523 else if (shCount >= (size * 8))
6526 /* get sign in acc.7 */
6527 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6528 addSign (result, LSB, sign);
6535 genrshOne (result, left, shCount, sign);
6539 genrshTwo (result, left, shCount, sign);
6543 genrshFour (result, left, shCount, sign);
6549 freeAsmop (left, NULL, ic, TRUE);
6550 freeAsmop (result, NULL, ic, TRUE);
6554 /*-----------------------------------------------------------------*/
6555 /* genSignedRightShift - right shift of signed number */
6556 /*-----------------------------------------------------------------*/
6558 genSignedRightShift (iCode * ic)
6560 operand *right, *left, *result;
6563 symbol *tlbl, *tlbl1;
6565 /* we do it the hard way put the shift count in b
6566 and loop thru preserving the sign */
6568 right = IC_RIGHT (ic);
6569 left = IC_LEFT (ic);
6570 result = IC_RESULT (ic);
6572 aopOp (right, ic, FALSE);
6575 if (AOP_TYPE (right) == AOP_LIT)
6577 genRightShiftLiteral (left, right, result, ic, 1);
6580 /* shift count is unknown then we have to form
6581 a loop get the loop count in B : Note: we take
6582 only the lower order byte since shifting
6583 more that 32 bits make no sense anyway, ( the
6584 largest size of an object can be only 32 bits ) */
6586 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6587 emitcode ("inc", "b");
6588 freeAsmop (right, NULL, ic, TRUE);
6589 aopOp (left, ic, FALSE);
6590 aopOp (result, ic, FALSE);
6592 /* now move the left to the result if they are not the
6594 if (!sameRegs (AOP (left), AOP (result)) &&
6595 AOP_SIZE (result) > 1)
6598 size = AOP_SIZE (result);
6602 l = aopGet (AOP (left), offset, FALSE, TRUE);
6603 if (*l == '@' && IS_AOP_PREG (result))
6606 emitcode ("mov", "a,%s", l);
6607 aopPut (AOP (result), "a", offset);
6610 aopPut (AOP (result), l, offset);
6615 /* mov the highest order bit to OVR */
6616 tlbl = newiTempLabel (NULL);
6617 tlbl1 = newiTempLabel (NULL);
6619 size = AOP_SIZE (result);
6621 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6622 emitcode ("rlc", "a");
6623 emitcode ("mov", "ov,c");
6624 /* if it is only one byte then */
6627 l = aopGet (AOP (left), 0, FALSE, FALSE);
6629 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6630 emitcode ("", "%05d$:", tlbl->key + 100);
6631 emitcode ("mov", "c,ov");
6632 emitcode ("rrc", "a");
6633 emitcode ("", "%05d$:", tlbl1->key + 100);
6634 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6635 aopPut (AOP (result), "a", 0);
6639 reAdjustPreg (AOP (result));
6640 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6641 emitcode ("", "%05d$:", tlbl->key + 100);
6642 emitcode ("mov", "c,ov");
6645 l = aopGet (AOP (result), offset, FALSE, FALSE);
6647 emitcode ("rrc", "a");
6648 aopPut (AOP (result), "a", offset--);
6650 reAdjustPreg (AOP (result));
6651 emitcode ("", "%05d$:", tlbl1->key + 100);
6652 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6655 freeAsmop (left, NULL, ic, TRUE);
6656 freeAsmop (result, NULL, ic, TRUE);
6659 /*-----------------------------------------------------------------*/
6660 /* genRightShift - generate code for right shifting */
6661 /*-----------------------------------------------------------------*/
6663 genRightShift (iCode * ic)
6665 operand *right, *left, *result;
6669 symbol *tlbl, *tlbl1;
6671 /* if signed then we do it the hard way preserve the
6672 sign bit moving it inwards */
6673 retype = getSpec (operandType (IC_RESULT (ic)));
6675 if (!SPEC_USIGN (retype))
6677 genSignedRightShift (ic);
6681 /* signed & unsigned types are treated the same : i.e. the
6682 signed is NOT propagated inwards : quoting from the
6683 ANSI - standard : "for E1 >> E2, is equivalent to division
6684 by 2**E2 if unsigned or if it has a non-negative value,
6685 otherwise the result is implementation defined ", MY definition
6686 is that the sign does not get propagated */
6688 right = IC_RIGHT (ic);
6689 left = IC_LEFT (ic);
6690 result = IC_RESULT (ic);
6692 aopOp (right, ic, FALSE);
6694 /* if the shift count is known then do it
6695 as efficiently as possible */
6696 if (AOP_TYPE (right) == AOP_LIT)
6698 genRightShiftLiteral (left, right, result, ic, 0);
6702 /* shift count is unknown then we have to form
6703 a loop get the loop count in B : Note: we take
6704 only the lower order byte since shifting
6705 more that 32 bits make no sense anyway, ( the
6706 largest size of an object can be only 32 bits ) */
6708 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6709 emitcode ("inc", "b");
6710 freeAsmop (right, NULL, ic, TRUE);
6711 aopOp (left, ic, FALSE);
6712 aopOp (result, ic, FALSE);
6714 /* now move the left to the result if they are not the
6716 if (!sameRegs (AOP (left), AOP (result)) &&
6717 AOP_SIZE (result) > 1)
6720 size = AOP_SIZE (result);
6724 l = aopGet (AOP (left), offset, FALSE, TRUE);
6725 if (*l == '@' && IS_AOP_PREG (result))
6728 emitcode ("mov", "a,%s", l);
6729 aopPut (AOP (result), "a", offset);
6732 aopPut (AOP (result), l, offset);
6737 tlbl = newiTempLabel (NULL);
6738 tlbl1 = newiTempLabel (NULL);
6739 size = AOP_SIZE (result);
6742 /* if it is only one byte then */
6745 l = aopGet (AOP (left), 0, FALSE, FALSE);
6747 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6748 emitcode ("", "%05d$:", tlbl->key + 100);
6750 emitcode ("rrc", "a");
6751 emitcode ("", "%05d$:", tlbl1->key + 100);
6752 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6753 aopPut (AOP (result), "a", 0);
6757 reAdjustPreg (AOP (result));
6758 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6759 emitcode ("", "%05d$:", tlbl->key + 100);
6763 l = aopGet (AOP (result), offset, FALSE, FALSE);
6765 emitcode ("rrc", "a");
6766 aopPut (AOP (result), "a", offset--);
6768 reAdjustPreg (AOP (result));
6770 emitcode ("", "%05d$:", tlbl1->key + 100);
6771 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6774 freeAsmop (left, NULL, ic, TRUE);
6775 freeAsmop (result, NULL, ic, TRUE);
6778 /*-----------------------------------------------------------------*/
6779 /* genUnpackBits - generates code for unpacking bits */
6780 /*-----------------------------------------------------------------*/
6782 genUnpackBits (operand * result, char *rname, int ptype)
6790 etype = getSpec (operandType (result));
6791 rsize = getSize (operandType (result));
6792 /* read the first byte */
6798 emitcode ("mov", "a,@%s", rname);
6802 emitcode ("movx", "a,@%s", rname);
6806 emitcode ("movx", "a,@dptr");
6810 emitcode ("clr", "a");
6811 emitcode ("movc", "a,@a+dptr");
6815 emitcode ("lcall", "__gptrget");
6819 rlen = SPEC_BLEN (etype);
6821 /* if we have bitdisplacement then it fits */
6822 /* into this byte completely or if length is */
6823 /* less than a byte */
6824 if ((shCnt = SPEC_BSTR (etype)) ||
6825 (SPEC_BLEN (etype) <= 8))
6828 /* shift right acc */
6831 emitcode ("anl", "a,#0x%02x",
6832 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6833 aopPut (AOP (result), "a", offset++);
6837 /* bit field did not fit in a byte */
6838 aopPut (AOP (result), "a", offset++);
6847 emitcode ("inc", "%s", rname);
6848 emitcode ("mov", "a,@%s", rname);
6852 emitcode ("inc", "%s", rname);
6853 emitcode ("movx", "a,@%s", rname);
6857 emitcode ("inc", "dptr");
6858 emitcode ("movx", "a,@dptr");
6862 emitcode ("clr", "a");
6863 emitcode ("inc", "dptr");
6864 emitcode ("movc", "a,@a+dptr");
6868 emitcode ("inc", "dptr");
6869 emitcode ("lcall", "__gptrget");
6874 /* if we are done */
6878 aopPut (AOP (result), "a", offset++);
6884 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6886 aopPut (AOP (result), "a", offset++);
6894 aopPut (AOP (result), zero, offset++);
6900 /*-----------------------------------------------------------------*/
6901 /* genDataPointerGet - generates code when ptr offset is known */
6902 /*-----------------------------------------------------------------*/
6904 genDataPointerGet (operand * left,
6910 int size, offset = 0;
6911 aopOp (result, ic, TRUE);
6913 /* get the string representation of the name */
6914 l = aopGet (AOP (left), 0, FALSE, TRUE);
6915 size = AOP_SIZE (result);
6919 sprintf (buffer, "(%s + %d)", l + 1, offset);
6921 sprintf (buffer, "%s", l + 1);
6922 aopPut (AOP (result), buffer, offset++);
6925 freeAsmop (left, NULL, ic, TRUE);
6926 freeAsmop (result, NULL, ic, TRUE);
6929 /*-----------------------------------------------------------------*/
6930 /* genNearPointerGet - emitcode for near pointer fetch */
6931 /*-----------------------------------------------------------------*/
6933 genNearPointerGet (operand * left,
6941 sym_link *rtype, *retype;
6942 sym_link *ltype = operandType (left);
6945 rtype = operandType (result);
6946 retype = getSpec (rtype);
6948 aopOp (left, ic, FALSE);
6950 /* if left is rematerialisable and
6951 result is not bit variable type and
6952 the left is pointer to data space i.e
6953 lower 128 bytes of space */
6954 if (AOP_TYPE (left) == AOP_IMMD &&
6955 !IS_BITVAR (retype) &&
6956 DCL_TYPE (ltype) == POINTER)
6958 genDataPointerGet (left, result, ic);
6962 /* if the value is already in a pointer register
6963 then don't need anything more */
6964 if (!AOP_INPREG (AOP (left)))
6966 /* otherwise get a free pointer register */
6968 preg = getFreePtr (ic, &aop, FALSE);
6969 emitcode ("mov", "%s,%s",
6971 aopGet (AOP (left), 0, FALSE, TRUE));
6975 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6977 //aopOp (result, ic, FALSE);
6978 aopOp (result, ic, result?TRUE:FALSE);
6980 /* if bitfield then unpack the bits */
6981 if (IS_BITVAR (retype))
6982 genUnpackBits (result, rname, POINTER);
6985 /* we have can just get the values */
6986 int size = AOP_SIZE (result);
6991 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6994 emitcode ("mov", "a,@%s", rname);
6995 aopPut (AOP (result), "a", offset);
6999 sprintf (buffer, "@%s", rname);
7000 aopPut (AOP (result), buffer, offset);
7004 emitcode ("inc", "%s", rname);
7008 /* now some housekeeping stuff */
7009 if (aop) /* we had to allocate for this iCode */
7011 if (pi) { /* post increment present */
7012 aopPut(AOP ( left ),rname,0);
7014 freeAsmop (NULL, aop, ic, TRUE);
7018 /* we did not allocate which means left
7019 already in a pointer register, then
7020 if size > 0 && this could be used again
7021 we have to point it back to where it
7023 if ((AOP_SIZE (result) > 1 &&
7024 !OP_SYMBOL (left)->remat &&
7025 (OP_SYMBOL (left)->liveTo > ic->seq ||
7029 int size = AOP_SIZE (result) - 1;
7031 emitcode ("dec", "%s", rname);
7036 freeAsmop (left, NULL, ic, TRUE);
7037 freeAsmop (result, NULL, ic, TRUE);
7038 if (pi) pi->generated = 1;
7041 /*-----------------------------------------------------------------*/
7042 /* genPagedPointerGet - emitcode for paged pointer fetch */
7043 /*-----------------------------------------------------------------*/
7045 genPagedPointerGet (operand * left,
7053 sym_link *rtype, *retype;
7055 rtype = operandType (result);
7056 retype = getSpec (rtype);
7058 aopOp (left, ic, FALSE);
7060 /* if the value is already in a pointer register
7061 then don't need anything more */
7062 if (!AOP_INPREG (AOP (left)))
7064 /* otherwise get a free pointer register */
7066 preg = getFreePtr (ic, &aop, FALSE);
7067 emitcode ("mov", "%s,%s",
7069 aopGet (AOP (left), 0, FALSE, TRUE));
7073 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7075 aopOp (result, ic, FALSE);
7077 /* if bitfield then unpack the bits */
7078 if (IS_BITVAR (retype))
7079 genUnpackBits (result, rname, PPOINTER);
7082 /* we have can just get the values */
7083 int size = AOP_SIZE (result);
7089 emitcode ("movx", "a,@%s", rname);
7090 aopPut (AOP (result), "a", offset);
7095 emitcode ("inc", "%s", rname);
7099 /* now some housekeeping stuff */
7100 if (aop) /* we had to allocate for this iCode */
7102 if (pi) aopPut ( AOP (left), rname, 0);
7103 freeAsmop (NULL, aop, ic, TRUE);
7107 /* we did not allocate which means left
7108 already in a pointer register, then
7109 if size > 0 && this could be used again
7110 we have to point it back to where it
7112 if ((AOP_SIZE (result) > 1 &&
7113 !OP_SYMBOL (left)->remat &&
7114 (OP_SYMBOL (left)->liveTo > ic->seq ||
7118 int size = AOP_SIZE (result) - 1;
7120 emitcode ("dec", "%s", rname);
7125 freeAsmop (left, NULL, ic, TRUE);
7126 freeAsmop (result, NULL, ic, TRUE);
7127 if (pi) pi->generated = 1;
7131 /*-----------------------------------------------------------------*/
7132 /* genFarPointerGet - gget value from far space */
7133 /*-----------------------------------------------------------------*/
7135 genFarPointerGet (operand * left,
7136 operand * result, iCode * ic, iCode * pi)
7139 sym_link *retype = getSpec (operandType (result));
7141 aopOp (left, ic, FALSE);
7143 /* if the operand is already in dptr
7144 then we do nothing else we move the value to dptr */
7145 if (AOP_TYPE (left) != AOP_STR)
7147 /* if this is remateriazable */
7148 if (AOP_TYPE (left) == AOP_IMMD)
7149 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7151 { /* we need to get it byte by byte */
7152 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7153 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7156 /* so dptr know contains the address */
7157 aopOp (result, ic, FALSE);
7159 /* if bit then unpack */
7160 if (IS_BITVAR (retype))
7161 genUnpackBits (result, "dptr", FPOINTER);
7164 size = AOP_SIZE (result);
7169 emitcode ("movx", "a,@dptr");
7170 aopPut (AOP (result), "a", offset++);
7172 emitcode ("inc", "dptr");
7176 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7177 aopPut ( AOP (left), "dpl", 0);
7178 aopPut ( AOP (left), "dph", 1);
7181 freeAsmop (left, NULL, ic, TRUE);
7182 freeAsmop (result, NULL, ic, TRUE);
7185 /*-----------------------------------------------------------------*/
7186 /* genCodePointerGet - gget value from code space */
7187 /*-----------------------------------------------------------------*/
7189 genCodePointerGet (operand * left,
7190 operand * result, iCode * ic, iCode *pi)
7193 sym_link *retype = getSpec (operandType (result));
7195 aopOp (left, ic, FALSE);
7197 /* if the operand is already in dptr
7198 then we do nothing else we move the value to dptr */
7199 if (AOP_TYPE (left) != AOP_STR)
7201 /* if this is remateriazable */
7202 if (AOP_TYPE (left) == AOP_IMMD)
7203 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7205 { /* we need to get it byte by byte */
7206 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7207 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7210 /* so dptr know contains the address */
7211 aopOp (result, ic, FALSE);
7213 /* if bit then unpack */
7214 if (IS_BITVAR (retype))
7215 genUnpackBits (result, "dptr", CPOINTER);
7218 size = AOP_SIZE (result);
7223 emitcode ("clr", "a");
7224 emitcode ("movc", "a,@a+dptr");
7225 aopPut (AOP (result), "a", offset++);
7227 emitcode ("inc", "dptr");
7231 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7232 aopPut ( AOP (left), "dpl", 0);
7233 aopPut ( AOP (left), "dph", 1);
7236 freeAsmop (left, NULL, ic, TRUE);
7237 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* genGenPointerGet - gget value from generic pointer space */
7242 /*-----------------------------------------------------------------*/
7244 genGenPointerGet (operand * left,
7245 operand * result, iCode * ic, iCode *pi)
7248 sym_link *retype = getSpec (operandType (result));
7250 aopOp (left, ic, FALSE);
7252 /* if the operand is already in dptr
7253 then we do nothing else we move the value to dptr */
7254 if (AOP_TYPE (left) != AOP_STR)
7256 /* if this is remateriazable */
7257 if (AOP_TYPE (left) == AOP_IMMD)
7259 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7260 emitcode ("mov", "b,#%d", pointerCode (retype));
7263 { /* we need to get it byte by byte */
7264 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7265 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7266 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7269 /* so dptr know contains the address */
7270 aopOp (result, ic, FALSE);
7272 /* if bit then unpack */
7273 if (IS_BITVAR (retype))
7274 genUnpackBits (result, "dptr", GPOINTER);
7277 size = AOP_SIZE (result);
7282 emitcode ("lcall", "__gptrget");
7283 aopPut (AOP (result), "a", offset++);
7285 emitcode ("inc", "dptr");
7289 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7290 aopPut ( AOP (left), "dpl", 0);
7291 aopPut ( AOP (left), "dph", 1);
7294 freeAsmop (left, NULL, ic, TRUE);
7295 freeAsmop (result, NULL, ic, TRUE);
7298 /*-----------------------------------------------------------------*/
7299 /* genPointerGet - generate code for pointer get */
7300 /*-----------------------------------------------------------------*/
7302 genPointerGet (iCode * ic, iCode *pi)
7304 operand *left, *result;
7305 sym_link *type, *etype;
7308 left = IC_LEFT (ic);
7309 result = IC_RESULT (ic);
7311 /* depending on the type of pointer we need to
7312 move it to the correct pointer register */
7313 type = operandType (left);
7314 etype = getSpec (type);
7315 /* if left is of type of pointer then it is simple */
7316 if (IS_PTR (type) && !IS_FUNC (type->next))
7317 p_type = DCL_TYPE (type);
7320 /* we have to go by the storage class */
7321 p_type = PTR_TYPE (SPEC_OCLS (etype));
7324 /* now that we have the pointer type we assign
7325 the pointer values */
7331 genNearPointerGet (left, result, ic, pi);
7335 genPagedPointerGet (left, result, ic, pi);
7339 genFarPointerGet (left, result, ic, pi);
7343 genCodePointerGet (left, result, ic, pi);
7347 genGenPointerGet (left, result, ic, pi);
7353 /*-----------------------------------------------------------------*/
7354 /* genPackBits - generates code for packed bit storage */
7355 /*-----------------------------------------------------------------*/
7357 genPackBits (sym_link * etype,
7359 char *rname, int p_type)
7367 blen = SPEC_BLEN (etype);
7368 bstr = SPEC_BSTR (etype);
7370 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7373 /* if the bit lenth is less than or */
7374 /* it exactly fits a byte then */
7375 if (SPEC_BLEN (etype) <= 8)
7377 shCount = SPEC_BSTR (etype);
7379 /* shift left acc */
7382 if (SPEC_BLEN (etype) < 8)
7383 { /* if smaller than a byte */
7389 emitcode ("mov", "b,a");
7390 emitcode ("mov", "a,@%s", rname);
7394 emitcode ("mov", "b,a");
7395 emitcode ("movx", "a,@dptr");
7399 emitcode ("push", "b");
7400 emitcode ("push", "acc");
7401 emitcode ("lcall", "__gptrget");
7402 emitcode ("pop", "b");
7406 emitcode ("anl", "a,#0x%02x", (unsigned char)
7407 ((unsigned char) (0xFF << (blen + bstr)) |
7408 (unsigned char) (0xFF >> (8 - bstr))));
7409 emitcode ("orl", "a,b");
7410 if (p_type == GPOINTER)
7411 emitcode ("pop", "b");
7418 emitcode ("mov", "@%s,a", rname);
7422 emitcode ("movx", "@dptr,a");
7426 emitcode ("lcall", "__gptrput");
7431 if (SPEC_BLEN (etype) <= 8)
7434 emitcode ("inc", "%s", rname);
7435 rLen = SPEC_BLEN (etype);
7437 /* now generate for lengths greater than one byte */
7441 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7453 emitcode ("mov", "@%s,a", rname);
7456 emitcode ("mov", "@%s,%s", rname, l);
7461 emitcode ("movx", "@dptr,a");
7466 emitcode ("lcall", "__gptrput");
7469 emitcode ("inc", "%s", rname);
7474 /* last last was not complete */
7477 /* save the byte & read byte */
7481 emitcode ("mov", "b,a");
7482 emitcode ("mov", "a,@%s", rname);
7486 emitcode ("mov", "b,a");
7487 emitcode ("movx", "a,@dptr");
7491 emitcode ("push", "b");
7492 emitcode ("push", "acc");
7493 emitcode ("lcall", "__gptrget");
7494 emitcode ("pop", "b");
7498 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7499 emitcode ("orl", "a,b");
7502 if (p_type == GPOINTER)
7503 emitcode ("pop", "b");
7509 emitcode ("mov", "@%s,a", rname);
7513 emitcode ("movx", "@dptr,a");
7517 emitcode ("lcall", "__gptrput");
7521 /*-----------------------------------------------------------------*/
7522 /* genDataPointerSet - remat pointer to data space */
7523 /*-----------------------------------------------------------------*/
7525 genDataPointerSet (operand * right,
7529 int size, offset = 0;
7530 char *l, buffer[256];
7532 aopOp (right, ic, FALSE);
7534 l = aopGet (AOP (result), 0, FALSE, TRUE);
7535 size = AOP_SIZE (right);
7539 sprintf (buffer, "(%s + %d)", l + 1, offset);
7541 sprintf (buffer, "%s", l + 1);
7542 emitcode ("mov", "%s,%s", buffer,
7543 aopGet (AOP (right), offset++, FALSE, FALSE));
7546 freeAsmop (right, NULL, ic, TRUE);
7547 freeAsmop (result, NULL, ic, TRUE);
7550 /*-----------------------------------------------------------------*/
7551 /* genNearPointerSet - emitcode for near pointer put */
7552 /*-----------------------------------------------------------------*/
7554 genNearPointerSet (operand * right,
7562 sym_link *retype, *letype;
7563 sym_link *ptype = operandType (result);
7565 retype = getSpec (operandType (right));
7566 letype = getSpec (ptype);
7567 aopOp (result, ic, FALSE);
7569 /* if the result is rematerializable &
7570 in data space & not a bit variable */
7571 if (AOP_TYPE (result) == AOP_IMMD &&
7572 DCL_TYPE (ptype) == POINTER &&
7573 !IS_BITVAR (retype) &&
7574 !IS_BITVAR (letype))
7576 genDataPointerSet (right, result, ic);
7580 /* if the value is already in a pointer register
7581 then don't need anything more */
7582 if (!AOP_INPREG (AOP (result)))
7584 /* otherwise get a free pointer register */
7586 preg = getFreePtr (ic, &aop, FALSE);
7587 emitcode ("mov", "%s,%s",
7589 aopGet (AOP (result), 0, FALSE, TRUE));
7593 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7595 aopOp (right, ic, FALSE);
7597 /* if bitfield then unpack the bits */
7598 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7599 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7602 /* we have can just get the values */
7603 int size = AOP_SIZE (right);
7608 l = aopGet (AOP (right), offset, FALSE, TRUE);
7612 emitcode ("mov", "@%s,a", rname);
7615 emitcode ("mov", "@%s,%s", rname, l);
7617 emitcode ("inc", "%s", rname);
7622 /* now some housekeeping stuff */
7623 if (aop) /* we had to allocate for this iCode */
7625 if (pi) aopPut (AOP (result),rname,0);
7626 freeAsmop (NULL, aop, ic, TRUE);
7630 /* we did not allocate which means left
7631 already in a pointer register, then
7632 if size > 0 && this could be used again
7633 we have to point it back to where it
7635 if ((AOP_SIZE (right) > 1 &&
7636 !OP_SYMBOL (result)->remat &&
7637 (OP_SYMBOL (result)->liveTo > ic->seq ||
7641 int size = AOP_SIZE (right) - 1;
7643 emitcode ("dec", "%s", rname);
7648 if (pi) pi->generated = 1;
7649 freeAsmop (result, NULL, ic, TRUE);
7650 freeAsmop (right, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genPagedPointerSet - emitcode for Paged pointer put */
7655 /*-----------------------------------------------------------------*/
7657 genPagedPointerSet (operand * right,
7665 sym_link *retype, *letype;
7667 retype = getSpec (operandType (right));
7668 letype = getSpec (operandType (result));
7670 aopOp (result, ic, FALSE);
7672 /* if the value is already in a pointer register
7673 then don't need anything more */
7674 if (!AOP_INPREG (AOP (result)))
7676 /* otherwise get a free pointer register */
7678 preg = getFreePtr (ic, &aop, FALSE);
7679 emitcode ("mov", "%s,%s",
7681 aopGet (AOP (result), 0, FALSE, TRUE));
7685 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7687 aopOp (right, ic, FALSE);
7689 /* if bitfield then unpack the bits */
7690 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7691 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7694 /* we have can just get the values */
7695 int size = AOP_SIZE (right);
7700 l = aopGet (AOP (right), offset, FALSE, TRUE);
7703 emitcode ("movx", "@%s,a", rname);
7706 emitcode ("inc", "%s", rname);
7712 /* now some housekeeping stuff */
7713 if (aop) /* we had to allocate for this iCode */
7715 if (pi) aopPut (AOP (result),rname,0);
7716 freeAsmop (NULL, aop, ic, TRUE);
7720 /* we did not allocate which means left
7721 already in a pointer register, then
7722 if size > 0 && this could be used again
7723 we have to point it back to where it
7725 if (AOP_SIZE (right) > 1 &&
7726 !OP_SYMBOL (result)->remat &&
7727 (OP_SYMBOL (result)->liveTo > ic->seq ||
7730 int size = AOP_SIZE (right) - 1;
7732 emitcode ("dec", "%s", rname);
7737 if (pi) pi->generated = 1;
7738 freeAsmop (result, NULL, ic, TRUE);
7739 freeAsmop (right, NULL, ic, TRUE);
7744 /*-----------------------------------------------------------------*/
7745 /* genFarPointerSet - set value from far space */
7746 /*-----------------------------------------------------------------*/
7748 genFarPointerSet (operand * right,
7749 operand * result, iCode * ic, iCode * pi)
7752 sym_link *retype = getSpec (operandType (right));
7753 sym_link *letype = getSpec (operandType (result));
7754 aopOp (result, ic, FALSE);
7756 /* if the operand is already in dptr
7757 then we do nothing else we move the value to dptr */
7758 if (AOP_TYPE (result) != AOP_STR)
7760 /* if this is remateriazable */
7761 if (AOP_TYPE (result) == AOP_IMMD)
7762 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7764 { /* we need to get it byte by byte */
7765 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7766 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7769 /* so dptr know contains the address */
7770 aopOp (right, ic, FALSE);
7772 /* if bit then unpack */
7773 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7774 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7777 size = AOP_SIZE (right);
7782 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7784 emitcode ("movx", "@dptr,a");
7786 emitcode ("inc", "dptr");
7789 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7790 aopPut (AOP(result),"dpl",0);
7791 aopPut (AOP(result),"dph",1);
7794 freeAsmop (result, NULL, ic, TRUE);
7795 freeAsmop (right, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genGenPointerSet - set value from generic pointer space */
7800 /*-----------------------------------------------------------------*/
7802 genGenPointerSet (operand * right,
7803 operand * result, iCode * ic, iCode * pi)
7806 sym_link *retype = getSpec (operandType (right));
7807 sym_link *letype = getSpec (operandType (result));
7809 aopOp (result, ic, FALSE);
7811 /* if the operand is already in dptr
7812 then we do nothing else we move the value to dptr */
7813 if (AOP_TYPE (result) != AOP_STR)
7815 /* if this is remateriazable */
7816 if (AOP_TYPE (result) == AOP_IMMD)
7818 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7819 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7822 { /* we need to get it byte by byte */
7823 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7824 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7825 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7828 /* so dptr know contains the address */
7829 aopOp (right, ic, FALSE);
7831 /* if bit then unpack */
7832 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7833 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7836 size = AOP_SIZE (right);
7841 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7843 emitcode ("lcall", "__gptrput");
7845 emitcode ("inc", "dptr");
7849 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7850 aopPut (AOP(result),"dpl",0);
7851 aopPut (AOP(result),"dph",1);
7854 freeAsmop (result, NULL, ic, TRUE);
7855 freeAsmop (right, NULL, ic, TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genPointerSet - stores the value into a pointer location */
7860 /*-----------------------------------------------------------------*/
7862 genPointerSet (iCode * ic, iCode *pi)
7864 operand *right, *result;
7865 sym_link *type, *etype;
7868 right = IC_RIGHT (ic);
7869 result = IC_RESULT (ic);
7871 /* depending on the type of pointer we need to
7872 move it to the correct pointer register */
7873 type = operandType (result);
7874 etype = getSpec (type);
7875 /* if left is of type of pointer then it is simple */
7876 if (IS_PTR (type) && !IS_FUNC (type->next))
7878 p_type = DCL_TYPE (type);
7882 /* we have to go by the storage class */
7883 p_type = PTR_TYPE (SPEC_OCLS (etype));
7886 /* now that we have the pointer type we assign
7887 the pointer values */
7893 genNearPointerSet (right, result, ic, pi);
7897 genPagedPointerSet (right, result, ic, pi);
7901 genFarPointerSet (right, result, ic, pi);
7905 genGenPointerSet (right, result, ic, pi);
7911 /*-----------------------------------------------------------------*/
7912 /* genIfx - generate code for Ifx statement */
7913 /*-----------------------------------------------------------------*/
7915 genIfx (iCode * ic, iCode * popIc)
7917 operand *cond = IC_COND (ic);
7920 aopOp (cond, ic, FALSE);
7922 /* get the value into acc */
7923 if (AOP_TYPE (cond) != AOP_CRY)
7927 /* the result is now in the accumulator */
7928 freeAsmop (cond, NULL, ic, TRUE);
7930 /* if there was something to be popped then do it */
7934 /* if the condition is a bit variable */
7935 if (isbit && IS_ITEMP (cond) &&
7937 genIfxJump (ic, SPIL_LOC (cond)->rname);
7938 else if (isbit && !IS_ITEMP (cond))
7939 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7941 genIfxJump (ic, "a");
7946 /*-----------------------------------------------------------------*/
7947 /* genAddrOf - generates code for address of */
7948 /*-----------------------------------------------------------------*/
7950 genAddrOf (iCode * ic)
7952 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7955 aopOp (IC_RESULT (ic), ic, FALSE);
7957 /* if the operand is on the stack then we
7958 need to get the stack offset of this
7962 /* if it has an offset then we need to compute
7966 emitcode ("mov", "a,_bp");
7967 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7968 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7972 /* we can just move _bp */
7973 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7975 /* fill the result with zero */
7976 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7981 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7987 /* object not on stack then we need the name */
7988 size = AOP_SIZE (IC_RESULT (ic));
7993 char s[SDCC_NAME_MAX];
7995 sprintf (s, "#(%s >> %d)",
7999 sprintf (s, "#%s", sym->rname);
8000 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8008 /*-----------------------------------------------------------------*/
8009 /* genFarFarAssign - assignment when both are in far space */
8010 /*-----------------------------------------------------------------*/
8012 genFarFarAssign (operand * result, operand * right, iCode * ic)
8014 int size = AOP_SIZE (right);
8017 /* first push the right side on to the stack */
8020 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8022 emitcode ("push", "acc");
8025 freeAsmop (right, NULL, ic, FALSE);
8026 /* now assign DPTR to result */
8027 aopOp (result, ic, FALSE);
8028 size = AOP_SIZE (result);
8031 emitcode ("pop", "acc");
8032 aopPut (AOP (result), "a", --offset);
8034 freeAsmop (result, NULL, ic, FALSE);
8038 /*-----------------------------------------------------------------*/
8039 /* genAssign - generate code for assignment */
8040 /*-----------------------------------------------------------------*/
8042 genAssign (iCode * ic)
8044 operand *result, *right;
8046 unsigned long lit = 0L;
8048 D(emitcode(";","genAssign"));
8050 result = IC_RESULT (ic);
8051 right = IC_RIGHT (ic);
8053 /* if they are the same */
8054 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8057 aopOp (right, ic, FALSE);
8059 /* special case both in far space */
8060 if (AOP_TYPE (right) == AOP_DPTR &&
8061 IS_TRUE_SYMOP (result) &&
8062 isOperandInFarSpace (result))
8065 genFarFarAssign (result, right, ic);
8069 aopOp (result, ic, TRUE);
8071 /* if they are the same registers */
8072 if (sameRegs (AOP (right), AOP (result)))
8075 /* if the result is a bit */
8076 if (AOP_TYPE (result) == AOP_CRY)
8079 /* if the right size is a literal then
8080 we know what the value is */
8081 if (AOP_TYPE (right) == AOP_LIT)
8083 if (((int) operandLitValue (right)))
8084 aopPut (AOP (result), one, 0);
8086 aopPut (AOP (result), zero, 0);
8090 /* the right is also a bit variable */
8091 if (AOP_TYPE (right) == AOP_CRY)
8093 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8094 aopPut (AOP (result), "c", 0);
8100 aopPut (AOP (result), "a", 0);
8104 /* bit variables done */
8106 size = AOP_SIZE (result);
8108 if (AOP_TYPE (right) == AOP_LIT)
8109 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8111 (AOP_TYPE (result) != AOP_REG) &&
8112 (AOP_TYPE (right) == AOP_LIT) &&
8113 !IS_FLOAT (operandType (right)) &&
8116 emitcode ("clr", "a");
8119 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8120 aopPut (AOP (result), "a", size);
8122 aopPut (AOP (result),
8123 aopGet (AOP (right), size, FALSE, FALSE),
8131 aopPut (AOP (result),
8132 aopGet (AOP (right), offset, FALSE, FALSE),
8139 freeAsmop (right, NULL, ic, TRUE);
8140 freeAsmop (result, NULL, ic, TRUE);
8143 /*-----------------------------------------------------------------*/
8144 /* genJumpTab - genrates code for jump table */
8145 /*-----------------------------------------------------------------*/
8147 genJumpTab (iCode * ic)
8152 aopOp (IC_JTCOND (ic), ic, FALSE);
8153 /* get the condition into accumulator */
8154 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8156 /* multiply by three */
8157 emitcode ("add", "a,acc");
8158 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8159 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8161 jtab = newiTempLabel (NULL);
8162 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8163 emitcode ("jmp", "@a+dptr");
8164 emitcode ("", "%05d$:", jtab->key + 100);
8165 /* now generate the jump labels */
8166 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8167 jtab = setNextItem (IC_JTLABELS (ic)))
8168 emitcode ("ljmp", "%05d$", jtab->key + 100);
8172 /*-----------------------------------------------------------------*/
8173 /* genCast - gen code for casting */
8174 /*-----------------------------------------------------------------*/
8176 genCast (iCode * ic)
8178 operand *result = IC_RESULT (ic);
8179 sym_link *ctype = operandType (IC_LEFT (ic));
8180 sym_link *rtype = operandType (IC_RIGHT (ic));
8181 operand *right = IC_RIGHT (ic);
8184 D(emitcode(";", "genCast"));
8186 /* if they are equivalent then do nothing */
8187 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8190 aopOp (right, ic, FALSE);
8191 aopOp (result, ic, FALSE);
8193 /* if the result is a bit */
8194 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8195 if (IS_BITVAR(OP_SYMBOL(result)->type))
8197 /* if the right size is a literal then
8198 we know what the value is */
8199 if (AOP_TYPE (right) == AOP_LIT)
8201 if (((int) operandLitValue (right)))
8202 aopPut (AOP (result), one, 0);
8204 aopPut (AOP (result), zero, 0);
8209 /* the right is also a bit variable */
8210 if (AOP_TYPE (right) == AOP_CRY)
8212 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8213 aopPut (AOP (result), "c", 0);
8219 aopPut (AOP (result), "a", 0);
8223 /* if they are the same size : or less */
8224 if (AOP_SIZE (result) <= AOP_SIZE (right))
8227 /* if they are in the same place */
8228 if (sameRegs (AOP (right), AOP (result)))
8231 /* if they in different places then copy */
8232 size = AOP_SIZE (result);
8236 aopPut (AOP (result),
8237 aopGet (AOP (right), offset, FALSE, FALSE),
8245 /* if the result is of type pointer */
8250 sym_link *type = operandType (right);
8251 sym_link *etype = getSpec (type);
8253 /* pointer to generic pointer */
8254 if (IS_GENPTR (ctype))
8259 p_type = DCL_TYPE (type);
8262 if (SPEC_SCLS(etype)==S_REGISTER) {
8263 // let's assume it is a generic pointer
8266 /* we have to go by the storage class */
8267 p_type = PTR_TYPE (SPEC_OCLS (etype));
8271 /* the first two bytes are known */
8272 size = GPTRSIZE - 1;
8276 aopPut (AOP (result),
8277 aopGet (AOP (right), offset, FALSE, FALSE),
8281 /* the last byte depending on type */
8297 case PPOINTER: // what the fck is this?
8302 /* this should never happen */
8303 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8304 "got unknown pointer type");
8307 aopPut (AOP (result), l, GPTRSIZE - 1);
8311 /* just copy the pointers */
8312 size = AOP_SIZE (result);
8316 aopPut (AOP (result),
8317 aopGet (AOP (right), offset, FALSE, FALSE),
8324 /* so we now know that the size of destination is greater
8325 than the size of the source */
8326 /* we move to result for the size of source */
8327 size = AOP_SIZE (right);
8331 aopPut (AOP (result),
8332 aopGet (AOP (right), offset, FALSE, FALSE),
8337 /* now depending on the sign of the source && destination */
8338 size = AOP_SIZE (result) - AOP_SIZE (right);
8339 /* if unsigned or not an integral type */
8340 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8343 aopPut (AOP (result), zero, offset++);
8347 /* we need to extend the sign :{ */
8348 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8351 emitcode ("rlc", "a");
8352 emitcode ("subb", "a,acc");
8354 aopPut (AOP (result), "a", offset++);
8357 /* we are done hurray !!!! */
8360 freeAsmop (right, NULL, ic, TRUE);
8361 freeAsmop (result, NULL, ic, TRUE);
8365 /*-----------------------------------------------------------------*/
8366 /* genDjnz - generate decrement & jump if not zero instrucion */
8367 /*-----------------------------------------------------------------*/
8369 genDjnz (iCode * ic, iCode * ifx)
8375 /* if the if condition has a false label
8376 then we cannot save */
8380 /* if the minus is not of the form
8382 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8383 !IS_OP_LITERAL (IC_RIGHT (ic)))
8386 if (operandLitValue (IC_RIGHT (ic)) != 1)
8389 /* if the size of this greater than one then no
8391 if (getSize (operandType (IC_RESULT (ic))) > 1)
8394 /* otherwise we can save BIG */
8395 lbl = newiTempLabel (NULL);
8396 lbl1 = newiTempLabel (NULL);
8398 aopOp (IC_RESULT (ic), ic, FALSE);
8400 if (AOP_NEEDSACC(IC_RESULT(ic)))
8402 /* If the result is accessed indirectly via
8403 * the accumulator, we must explicitly write
8404 * it back after the decrement.
8406 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8408 if (strcmp(rByte, "a"))
8410 /* Something is hopelessly wrong */
8411 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8412 __FILE__, __LINE__);
8413 /* We can just give up; the generated code will be inefficient,
8416 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8419 emitcode ("dec", "%s", rByte);
8420 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8421 emitcode ("jnz", "%05d$", lbl->key + 100);
8423 else if (IS_AOP_PREG (IC_RESULT (ic)))
8425 emitcode ("dec", "%s",
8426 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8427 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8428 emitcode ("jnz", "%05d$", lbl->key + 100);
8432 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8435 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8436 emitcode ("", "%05d$:", lbl->key + 100);
8437 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8438 emitcode ("", "%05d$:", lbl1->key + 100);
8440 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8445 /*-----------------------------------------------------------------*/
8446 /* genReceive - generate code for a receive iCode */
8447 /*-----------------------------------------------------------------*/
8449 genReceive (iCode * ic)
8451 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8452 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8453 IS_TRUE_SYMOP (IC_RESULT (ic))))
8456 int size = getSize (operandType (IC_RESULT (ic)));
8457 int offset = fReturnSizeMCS51 - size;
8460 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8461 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8464 aopOp (IC_RESULT (ic), ic, FALSE);
8465 size = AOP_SIZE (IC_RESULT (ic));
8469 emitcode ("pop", "acc");
8470 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8477 aopOp (IC_RESULT (ic), ic, FALSE);
8479 assignResultValue (IC_RESULT (ic));
8482 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* gen51AggregateAssign - copy complete array's or structures */
8487 /*-----------------------------------------------------------------*/
8488 void gen51AggregateAssign(iCode *ic) {
8489 operand *left=IC_LEFT(ic);
8490 operand *right=IC_RIGHT(ic);
8491 char *fromName=OP_SYMBOL(right)->rname;
8492 char *toName=OP_SYMBOL(left)->rname;
8493 int fromSize=getSize(OP_SYMBOL(right)->type);
8494 int toSize=getSize(OP_SYMBOL(left)->type);
8497 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8498 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8499 // well, this code isn't used yet from anywhere else as for initialising
8500 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8504 if (fromSize!=toSize) {
8505 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8506 ic->filename, ic->lineno);
8511 // use the generic memcpy() for now
8512 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8513 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8514 emitcode ("mov", "a,#%s", fromName);
8515 emitcode ("movx", "@dptr,a");
8516 emitcode ("inc", "dptr");
8517 emitcode ("mov", "a,#(%s>>8)", fromName);
8518 emitcode ("movx", "@dptr,a");
8519 emitcode ("inc", "dptr");
8520 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8521 emitcode ("movx", "@dptr,a");
8522 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8523 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8524 emitcode ("movx", "@dptr,a");
8525 emitcode ("inc", "dptr");
8526 emitcode ("mov", "a,#(%d>>8)", count);
8527 emitcode ("movx", "@dptr,a");
8528 emitcode ("mov", "dptr,#%s", toName);
8529 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8530 emitcode ("lcall", "_memcpy");
8532 // more efficient, but will require the native_memcpy_cs2xs
8533 emitcode ("mov", "r0,#%s", fromName);
8534 emitcode ("mov", "r1,#(%s>>8)", fromName);
8535 emitcode ("mov", "r2,#%s", toName);
8536 emitcode ("mov", "r3,#(%s>>8)", toName);
8537 emitcode ("mov", "r4,#%d", count);
8538 emitcode ("mov", "r5,#(%d>>8)", count);
8539 emitcode ("lcall", "_native_memcpy_cs2xs");
8543 /*-----------------------------------------------------------------*/
8544 /* gen51Code - generate code for 8051 based controllers */
8545 /*-----------------------------------------------------------------*/
8547 gen51Code (iCode * lic)
8552 lineHead = lineCurr = NULL;
8554 /* print the allocation information */
8556 printAllocInfo (currFunc, codeOutFile);
8557 /* if debug information required */
8558 /* if (options.debug && currFunc) { */
8559 if (options.debug && currFunc)
8561 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8563 if (IS_STATIC (currFunc->etype))
8564 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8566 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8569 /* stack pointer name */
8570 if (options.useXstack)
8576 for (ic = lic; ic; ic = ic->next)
8579 if (cln != ic->lineno)
8584 emitcode ("", "C$%s$%d$%d$%d ==.",
8585 FileBaseName (ic->filename), ic->lineno,
8586 ic->level, ic->block);
8589 emitcode (";", "%s %d", ic->filename, ic->lineno);
8592 /* if the result is marked as
8593 spilt and rematerializable or code for
8594 this has already been generated then
8596 if (resultRemat (ic) || ic->generated)
8599 /* depending on the operation */
8619 /* IPOP happens only when trying to restore a
8620 spilt live range, if there is an ifx statement
8621 following this pop then the if statement might
8622 be using some of the registers being popped which
8623 would destory the contents of the register so
8624 we need to check for this condition and handle it */
8626 ic->next->op == IFX &&
8627 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8628 genIfx (ic->next, ic);
8646 genEndFunction (ic);
8666 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8683 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8687 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8694 /* note these two are xlated by algebraic equivalence
8695 during parsing SDCC.y */
8696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8697 "got '>=' or '<=' shouldn't have come here");
8701 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8713 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8717 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8721 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8748 case GET_VALUE_AT_ADDRESS:
8749 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8753 if (POINTER_SET (ic))
8754 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8780 addSet (&_G.sendSet, ic);
8784 gen51AggregateAssign(ic);
8793 /* now we are ready to call the
8794 peep hole optimizer */
8795 if (!options.nopeep)
8796 peepHole (&lineHead);
8798 /* now do the actual printing */
8799 printLine (lineHead, codeOutFile);