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 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4212 isize = getSize(type->next);
4214 /* if operand of the form op = op + <sizeof *op> */
4215 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4216 isOperandEqual(IC_RESULT(lic),op) &&
4217 isOperandLiteral(IC_RIGHT(lic)) &&
4218 operandLitValue(IC_RIGHT(lic)) == isize) {
4221 /* if the operand used or deffed */
4222 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4230 /*-----------------------------------------------------------------*/
4231 /* genAndOp - for && operation */
4232 /*-----------------------------------------------------------------*/
4234 genAndOp (iCode * ic)
4236 operand *left, *right, *result;
4239 /* note here that && operations that are in an
4240 if statement are taken away by backPatchLabels
4241 only those used in arthmetic operations remain */
4242 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4243 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4244 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4246 /* if both are bit variables */
4247 if (AOP_TYPE (left) == AOP_CRY &&
4248 AOP_TYPE (right) == AOP_CRY)
4250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4251 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4256 tlbl = newiTempLabel (NULL);
4258 emitcode ("jz", "%05d$", tlbl->key + 100);
4260 emitcode ("", "%05d$:", tlbl->key + 100);
4264 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4265 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4266 freeAsmop (result, NULL, ic, TRUE);
4270 /*-----------------------------------------------------------------*/
4271 /* genOrOp - for || operation */
4272 /*-----------------------------------------------------------------*/
4274 genOrOp (iCode * ic)
4276 operand *left, *right, *result;
4279 /* note here that || operations that are in an
4280 if statement are taken away by backPatchLabels
4281 only those used in arthmetic operations remain */
4282 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4283 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4284 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4286 /* if both are bit variables */
4287 if (AOP_TYPE (left) == AOP_CRY &&
4288 AOP_TYPE (right) == AOP_CRY)
4290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4291 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4296 tlbl = newiTempLabel (NULL);
4298 emitcode ("jnz", "%05d$", tlbl->key + 100);
4300 emitcode ("", "%05d$:", tlbl->key + 100);
4304 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4306 freeAsmop (result, NULL, ic, TRUE);
4309 /*-----------------------------------------------------------------*/
4310 /* isLiteralBit - test if lit == 2^n */
4311 /*-----------------------------------------------------------------*/
4313 isLiteralBit (unsigned long lit)
4315 unsigned long pw[32] =
4316 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4317 0x100L, 0x200L, 0x400L, 0x800L,
4318 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4319 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4320 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4321 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4322 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4325 for (idx = 0; idx < 32; idx++)
4331 /*-----------------------------------------------------------------*/
4332 /* continueIfTrue - */
4333 /*-----------------------------------------------------------------*/
4335 continueIfTrue (iCode * ic)
4338 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4342 /*-----------------------------------------------------------------*/
4344 /*-----------------------------------------------------------------*/
4346 jumpIfTrue (iCode * ic)
4349 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4353 /*-----------------------------------------------------------------*/
4354 /* jmpTrueOrFalse - */
4355 /*-----------------------------------------------------------------*/
4357 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4359 // ugly but optimized by peephole
4362 symbol *nlbl = newiTempLabel (NULL);
4363 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4364 emitcode ("", "%05d$:", tlbl->key + 100);
4365 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4366 emitcode ("", "%05d$:", nlbl->key + 100);
4370 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4371 emitcode ("", "%05d$:", tlbl->key + 100);
4376 /*-----------------------------------------------------------------*/
4377 /* genAnd - code for and */
4378 /*-----------------------------------------------------------------*/
4380 genAnd (iCode * ic, iCode * ifx)
4382 operand *left, *right, *result;
4383 int size, offset = 0;
4384 unsigned long lit = 0L;
4388 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4389 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4390 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4393 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4395 AOP_TYPE (left), AOP_TYPE (right));
4396 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4398 AOP_SIZE (left), AOP_SIZE (right));
4401 /* if left is a literal & right is not then exchange them */
4402 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4403 AOP_NEEDSACC (left))
4405 operand *tmp = right;
4410 /* if result = right then exchange them */
4411 if (sameRegs (AOP (result), AOP (right)))
4413 operand *tmp = right;
4418 /* if right is bit then exchange them */
4419 if (AOP_TYPE (right) == AOP_CRY &&
4420 AOP_TYPE (left) != AOP_CRY)
4422 operand *tmp = right;
4426 if (AOP_TYPE (right) == AOP_LIT)
4427 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4429 size = AOP_SIZE (result);
4432 // result = bit & yy;
4433 if (AOP_TYPE (left) == AOP_CRY)
4435 // c = bit & literal;
4436 if (AOP_TYPE (right) == AOP_LIT)
4440 if (size && sameRegs (AOP (result), AOP (left)))
4443 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4448 if (size && (AOP_TYPE (result) == AOP_CRY))
4450 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4453 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4458 emitcode ("clr", "c");
4463 if (AOP_TYPE (right) == AOP_CRY)
4466 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4467 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4472 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4474 emitcode ("rrc", "a");
4475 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4483 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4484 genIfxJump (ifx, "c");
4488 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4489 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4490 if ((AOP_TYPE (right) == AOP_LIT) &&
4491 (AOP_TYPE (result) == AOP_CRY) &&
4492 (AOP_TYPE (left) != AOP_CRY))
4494 int posbit = isLiteralBit (lit);
4499 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4502 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4508 sprintf (buffer, "acc.%d", posbit & 0x07);
4509 genIfxJump (ifx, buffer);
4516 symbol *tlbl = newiTempLabel (NULL);
4517 int sizel = AOP_SIZE (left);
4519 emitcode ("setb", "c");
4522 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4524 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4526 if ((posbit = isLiteralBit (bytelit)) != 0)
4527 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4530 if (bytelit != 0x0FFL)
4531 emitcode ("anl", "a,%s",
4532 aopGet (AOP (right), offset, FALSE, TRUE));
4533 emitcode ("jnz", "%05d$", tlbl->key + 100);
4538 // bit = left & literal
4541 emitcode ("clr", "c");
4542 emitcode ("", "%05d$:", tlbl->key + 100);
4544 // if(left & literal)
4548 jmpTrueOrFalse (ifx, tlbl);
4556 /* if left is same as result */
4557 if (sameRegs (AOP (result), AOP (left)))
4559 for (; size--; offset++)
4561 if (AOP_TYPE (right) == AOP_LIT)
4563 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4565 else if (bytelit == 0)
4566 aopPut (AOP (result), zero, offset);
4567 else if (IS_AOP_PREG (result))
4569 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4570 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4571 aopPut (AOP (result), "a", offset);
4574 emitcode ("anl", "%s,%s",
4575 aopGet (AOP (left), offset, FALSE, TRUE),
4576 aopGet (AOP (right), offset, FALSE, FALSE));
4580 if (AOP_TYPE (left) == AOP_ACC)
4581 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4584 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4585 if (IS_AOP_PREG (result))
4587 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4588 aopPut (AOP (result), "a", offset);
4592 emitcode ("anl", "%s,a",
4593 aopGet (AOP (left), offset, FALSE, TRUE));
4600 // left & result in different registers
4601 if (AOP_TYPE (result) == AOP_CRY)
4604 // if(size), result in bit
4605 // if(!size && ifx), conditional oper: if(left & right)
4606 symbol *tlbl = newiTempLabel (NULL);
4607 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4609 emitcode ("setb", "c");
4612 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4613 emitcode ("anl", "a,%s",
4614 aopGet (AOP (right), offset, FALSE, FALSE));
4616 if (AOP_TYPE(left)==AOP_ACC) {
4617 emitcode("mov", "b,a");
4618 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4619 emitcode("anl", "a,b");
4621 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4622 emitcode ("anl", "a,%s",
4623 aopGet (AOP (left), offset, FALSE, FALSE));
4626 emitcode ("jnz", "%05d$", tlbl->key + 100);
4632 emitcode ("", "%05d$:", tlbl->key + 100);
4636 jmpTrueOrFalse (ifx, tlbl);
4640 for (; (size--); offset++)
4643 // result = left & right
4644 if (AOP_TYPE (right) == AOP_LIT)
4646 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4648 aopPut (AOP (result),
4649 aopGet (AOP (left), offset, FALSE, FALSE),
4653 else if (bytelit == 0)
4655 aopPut (AOP (result), zero, offset);
4659 // faster than result <- left, anl result,right
4660 // and better if result is SFR
4661 if (AOP_TYPE (left) == AOP_ACC)
4662 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4665 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4666 emitcode ("anl", "a,%s",
4667 aopGet (AOP (left), offset, FALSE, FALSE));
4669 aopPut (AOP (result), "a", offset);
4675 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4676 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4677 freeAsmop (result, NULL, ic, TRUE);
4680 /*-----------------------------------------------------------------*/
4681 /* genOr - code for or */
4682 /*-----------------------------------------------------------------*/
4684 genOr (iCode * ic, iCode * ifx)
4686 operand *left, *right, *result;
4687 int size, offset = 0;
4688 unsigned long lit = 0L;
4690 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4691 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4692 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4695 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4697 AOP_TYPE (left), AOP_TYPE (right));
4698 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4700 AOP_SIZE (left), AOP_SIZE (right));
4703 /* if left is a literal & right is not then exchange them */
4704 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4705 AOP_NEEDSACC (left))
4707 operand *tmp = right;
4712 /* if result = right then exchange them */
4713 if (sameRegs (AOP (result), AOP (right)))
4715 operand *tmp = right;
4720 /* if right is bit then exchange them */
4721 if (AOP_TYPE (right) == AOP_CRY &&
4722 AOP_TYPE (left) != AOP_CRY)
4724 operand *tmp = right;
4728 if (AOP_TYPE (right) == AOP_LIT)
4729 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4731 size = AOP_SIZE (result);
4735 if (AOP_TYPE (left) == AOP_CRY)
4737 if (AOP_TYPE (right) == AOP_LIT)
4739 // c = bit & literal;
4742 // lit != 0 => result = 1
4743 if (AOP_TYPE (result) == AOP_CRY)
4746 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4748 continueIfTrue (ifx);
4751 emitcode ("setb", "c");
4755 // lit == 0 => result = left
4756 if (size && sameRegs (AOP (result), AOP (left)))
4758 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4763 if (AOP_TYPE (right) == AOP_CRY)
4766 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4767 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4772 symbol *tlbl = newiTempLabel (NULL);
4773 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4774 emitcode ("setb", "c");
4775 emitcode ("jb", "%s,%05d$",
4776 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4778 emitcode ("jnz", "%05d$", tlbl->key + 100);
4779 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4781 jmpTrueOrFalse (ifx, tlbl);
4787 emitcode ("", "%05d$:", tlbl->key + 100);
4796 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4797 genIfxJump (ifx, "c");
4801 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4802 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4803 if ((AOP_TYPE (right) == AOP_LIT) &&
4804 (AOP_TYPE (result) == AOP_CRY) &&
4805 (AOP_TYPE (left) != AOP_CRY))
4811 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4813 continueIfTrue (ifx);
4818 // lit = 0, result = boolean(left)
4820 emitcode ("setb", "c");
4824 symbol *tlbl = newiTempLabel (NULL);
4825 emitcode ("jnz", "%05d$", tlbl->key + 100);
4827 emitcode ("", "%05d$:", tlbl->key + 100);
4831 genIfxJump (ifx, "a");
4839 /* if left is same as result */
4840 if (sameRegs (AOP (result), AOP (left)))
4842 for (; size--; offset++)
4844 if (AOP_TYPE (right) == AOP_LIT)
4846 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4848 else if (IS_AOP_PREG (left))
4850 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4851 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4852 aopPut (AOP (result), "a", offset);
4855 emitcode ("orl", "%s,%s",
4856 aopGet (AOP (left), offset, FALSE, TRUE),
4857 aopGet (AOP (right), offset, FALSE, FALSE));
4861 if (AOP_TYPE (left) == AOP_ACC)
4862 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4865 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4866 if (IS_AOP_PREG (left))
4868 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4869 aopPut (AOP (result), "a", offset);
4872 emitcode ("orl", "%s,a",
4873 aopGet (AOP (left), offset, FALSE, TRUE));
4880 // left & result in different registers
4881 if (AOP_TYPE (result) == AOP_CRY)
4884 // if(size), result in bit
4885 // if(!size && ifx), conditional oper: if(left | right)
4886 symbol *tlbl = newiTempLabel (NULL);
4887 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4889 emitcode ("setb", "c");
4892 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4893 emitcode ("orl", "a,%s",
4894 aopGet (AOP (right), offset, FALSE, FALSE));
4896 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4897 emitcode ("orl", "a,%s",
4898 aopGet (AOP (left), offset, FALSE, FALSE));
4900 emitcode ("jnz", "%05d$", tlbl->key + 100);
4906 emitcode ("", "%05d$:", tlbl->key + 100);
4910 jmpTrueOrFalse (ifx, tlbl);
4913 for (; (size--); offset++)
4916 // result = left & right
4917 if (AOP_TYPE (right) == AOP_LIT)
4919 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4921 aopPut (AOP (result),
4922 aopGet (AOP (left), offset, FALSE, FALSE),
4927 // faster than result <- left, anl result,right
4928 // and better if result is SFR
4929 if (AOP_TYPE (left) == AOP_ACC)
4930 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4934 emitcode ("orl", "a,%s",
4935 aopGet (AOP (left), offset, FALSE, FALSE));
4937 aopPut (AOP (result), "a", offset);
4942 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genXor - code for xclusive or */
4949 /*-----------------------------------------------------------------*/
4951 genXor (iCode * ic, iCode * ifx)
4953 operand *left, *right, *result;
4954 int size, offset = 0;
4955 unsigned long lit = 0L;
4957 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4958 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4959 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4962 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4964 AOP_TYPE (left), AOP_TYPE (right));
4965 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4967 AOP_SIZE (left), AOP_SIZE (right));
4970 /* if left is a literal & right is not ||
4971 if left needs acc & right does not */
4972 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4973 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4975 operand *tmp = right;
4980 /* if result = right then exchange them */
4981 if (sameRegs (AOP (result), AOP (right)))
4983 operand *tmp = right;
4988 /* if right is bit then exchange them */
4989 if (AOP_TYPE (right) == AOP_CRY &&
4990 AOP_TYPE (left) != AOP_CRY)
4992 operand *tmp = right;
4996 if (AOP_TYPE (right) == AOP_LIT)
4997 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4999 size = AOP_SIZE (result);
5003 if (AOP_TYPE (left) == AOP_CRY)
5005 if (AOP_TYPE (right) == AOP_LIT)
5007 // c = bit & literal;
5010 // lit>>1 != 0 => result = 1
5011 if (AOP_TYPE (result) == AOP_CRY)
5014 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5016 continueIfTrue (ifx);
5019 emitcode ("setb", "c");
5026 // lit == 0, result = left
5027 if (size && sameRegs (AOP (result), AOP (left)))
5029 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5033 // lit == 1, result = not(left)
5034 if (size && sameRegs (AOP (result), AOP (left)))
5036 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5041 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5042 emitcode ("cpl", "c");
5051 symbol *tlbl = newiTempLabel (NULL);
5052 if (AOP_TYPE (right) == AOP_CRY)
5055 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5059 int sizer = AOP_SIZE (right);
5061 // if val>>1 != 0, result = 1
5062 emitcode ("setb", "c");
5065 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5067 // test the msb of the lsb
5068 emitcode ("anl", "a,#0xfe");
5069 emitcode ("jnz", "%05d$", tlbl->key + 100);
5073 emitcode ("rrc", "a");
5075 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5076 emitcode ("cpl", "c");
5077 emitcode ("", "%05d$:", (tlbl->key + 100));
5084 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5085 genIfxJump (ifx, "c");
5089 if (sameRegs (AOP (result), AOP (left)))
5091 /* if left is same as result */
5092 for (; size--; offset++)
5094 if (AOP_TYPE (right) == AOP_LIT)
5096 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5098 else if (IS_AOP_PREG (left))
5100 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5101 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5102 aopPut (AOP (result), "a", offset);
5105 emitcode ("xrl", "%s,%s",
5106 aopGet (AOP (left), offset, FALSE, TRUE),
5107 aopGet (AOP (right), offset, FALSE, FALSE));
5111 if (AOP_TYPE (left) == AOP_ACC)
5112 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5116 if (IS_AOP_PREG (left))
5118 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5119 aopPut (AOP (result), "a", offset);
5122 emitcode ("xrl", "%s,a",
5123 aopGet (AOP (left), offset, FALSE, TRUE));
5130 // left & result in different registers
5131 if (AOP_TYPE (result) == AOP_CRY)
5134 // if(size), result in bit
5135 // if(!size && ifx), conditional oper: if(left ^ right)
5136 symbol *tlbl = newiTempLabel (NULL);
5137 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5139 emitcode ("setb", "c");
5142 if ((AOP_TYPE (right) == AOP_LIT) &&
5143 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5145 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5149 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5150 emitcode ("xrl", "a,%s",
5151 aopGet (AOP (right), offset, FALSE, FALSE));
5153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5154 emitcode ("xrl", "a,%s",
5155 aopGet (AOP (left), offset, FALSE, FALSE));
5158 emitcode ("jnz", "%05d$", tlbl->key + 100);
5164 emitcode ("", "%05d$:", tlbl->key + 100);
5168 jmpTrueOrFalse (ifx, tlbl);
5171 for (; (size--); offset++)
5174 // result = left & right
5175 if (AOP_TYPE (right) == AOP_LIT)
5177 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5179 aopPut (AOP (result),
5180 aopGet (AOP (left), offset, FALSE, FALSE),
5185 // faster than result <- left, anl result,right
5186 // and better if result is SFR
5187 if (AOP_TYPE (left) == AOP_ACC)
5188 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5191 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5192 emitcode ("xrl", "a,%s",
5193 aopGet (AOP (left), offset, FALSE, TRUE));
5195 aopPut (AOP (result), "a", offset);
5200 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202 freeAsmop (result, NULL, ic, TRUE);
5205 /*-----------------------------------------------------------------*/
5206 /* genInline - write the inline code out */
5207 /*-----------------------------------------------------------------*/
5209 genInline (iCode * ic)
5211 char *buffer, *bp, *bp1;
5213 _G.inLine += (!options.asmpeep);
5215 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5216 strcpy (buffer, IC_INLINE (ic));
5218 /* emit each line as a code */
5243 /* emitcode("",buffer); */
5244 _G.inLine -= (!options.asmpeep);
5247 /*-----------------------------------------------------------------*/
5248 /* genRRC - rotate right with carry */
5249 /*-----------------------------------------------------------------*/
5253 operand *left, *result;
5254 int size, offset = 0;
5257 /* rotate right with carry */
5258 left = IC_LEFT (ic);
5259 result = IC_RESULT (ic);
5260 aopOp (left, ic, FALSE);
5261 aopOp (result, ic, FALSE);
5263 /* move it to the result */
5264 size = AOP_SIZE (result);
5266 if (size == 1) { /* special case for 1 byte */
5267 l = aopGet (AOP (left), offset, FALSE, FALSE);
5269 emitcode ("rr", "a");
5275 l = aopGet (AOP (left), offset, FALSE, FALSE);
5277 emitcode ("rrc", "a");
5278 if (AOP_SIZE (result) > 1)
5279 aopPut (AOP (result), "a", offset--);
5281 /* now we need to put the carry into the
5282 highest order byte of the result */
5283 if (AOP_SIZE (result) > 1)
5285 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5288 emitcode ("mov", "acc.7,c");
5290 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5291 freeAsmop (left, NULL, ic, TRUE);
5292 freeAsmop (result, NULL, ic, TRUE);
5295 /*-----------------------------------------------------------------*/
5296 /* genRLC - generate code for rotate left with carry */
5297 /*-----------------------------------------------------------------*/
5301 operand *left, *result;
5302 int size, offset = 0;
5305 /* rotate right with carry */
5306 left = IC_LEFT (ic);
5307 result = IC_RESULT (ic);
5308 aopOp (left, ic, FALSE);
5309 aopOp (result, ic, FALSE);
5311 /* move it to the result */
5312 size = AOP_SIZE (result);
5316 l = aopGet (AOP (left), offset, FALSE, FALSE);
5318 if (size == 0) { /* special case for 1 byte */
5322 emitcode ("add", "a,acc");
5323 if (AOP_SIZE (result) > 1)
5324 aopPut (AOP (result), "a", offset++);
5327 l = aopGet (AOP (left), offset, FALSE, FALSE);
5329 emitcode ("rlc", "a");
5330 if (AOP_SIZE (result) > 1)
5331 aopPut (AOP (result), "a", offset++);
5334 /* now we need to put the carry into the
5335 highest order byte of the result */
5336 if (AOP_SIZE (result) > 1)
5338 l = aopGet (AOP (result), 0, FALSE, FALSE);
5341 emitcode ("mov", "acc.0,c");
5343 aopPut (AOP (result), "a", 0);
5344 freeAsmop (left, NULL, ic, TRUE);
5345 freeAsmop (result, NULL, ic, TRUE);
5348 /*-----------------------------------------------------------------*/
5349 /* genGetHbit - generates code get highest order bit */
5350 /*-----------------------------------------------------------------*/
5352 genGetHbit (iCode * ic)
5354 operand *left, *result;
5355 left = IC_LEFT (ic);
5356 result = IC_RESULT (ic);
5357 aopOp (left, ic, FALSE);
5358 aopOp (result, ic, FALSE);
5360 /* get the highest order byte into a */
5361 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5362 if (AOP_TYPE (result) == AOP_CRY)
5364 emitcode ("rlc", "a");
5369 emitcode ("rl", "a");
5370 emitcode ("anl", "a,#0x01");
5375 freeAsmop (left, NULL, ic, TRUE);
5376 freeAsmop (result, NULL, ic, TRUE);
5379 /*-----------------------------------------------------------------*/
5380 /* AccRol - rotate left accumulator by known count */
5381 /*-----------------------------------------------------------------*/
5383 AccRol (int shCount)
5385 shCount &= 0x0007; // shCount : 0..7
5392 emitcode ("rl", "a");
5395 emitcode ("rl", "a");
5396 emitcode ("rl", "a");
5399 emitcode ("swap", "a");
5400 emitcode ("rr", "a");
5403 emitcode ("swap", "a");
5406 emitcode ("swap", "a");
5407 emitcode ("rl", "a");
5410 emitcode ("rr", "a");
5411 emitcode ("rr", "a");
5414 emitcode ("rr", "a");
5419 /*-----------------------------------------------------------------*/
5420 /* AccLsh - left shift accumulator by known count */
5421 /*-----------------------------------------------------------------*/
5423 AccLsh (int shCount)
5428 emitcode ("add", "a,acc");
5429 else if (shCount == 2)
5431 emitcode ("add", "a,acc");
5432 emitcode ("add", "a,acc");
5436 /* rotate left accumulator */
5438 /* and kill the lower order bits */
5439 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5444 /*-----------------------------------------------------------------*/
5445 /* AccRsh - right shift accumulator by known count */
5446 /*-----------------------------------------------------------------*/
5448 AccRsh (int shCount)
5455 emitcode ("rrc", "a");
5459 /* rotate right accumulator */
5460 AccRol (8 - shCount);
5461 /* and kill the higher order bits */
5462 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5467 /*-----------------------------------------------------------------*/
5468 /* AccSRsh - signed right shift accumulator by known count */
5469 /*-----------------------------------------------------------------*/
5471 AccSRsh (int shCount)
5478 emitcode ("mov", "c,acc.7");
5479 emitcode ("rrc", "a");
5481 else if (shCount == 2)
5483 emitcode ("mov", "c,acc.7");
5484 emitcode ("rrc", "a");
5485 emitcode ("mov", "c,acc.7");
5486 emitcode ("rrc", "a");
5490 tlbl = newiTempLabel (NULL);
5491 /* rotate right accumulator */
5492 AccRol (8 - shCount);
5493 /* and kill the higher order bits */
5494 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5495 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5496 emitcode ("orl", "a,#0x%02x",
5497 (unsigned char) ~SRMask[shCount]);
5498 emitcode ("", "%05d$:", tlbl->key + 100);
5503 /*-----------------------------------------------------------------*/
5504 /* shiftR1Left2Result - shift right one byte from left to result */
5505 /*-----------------------------------------------------------------*/
5507 shiftR1Left2Result (operand * left, int offl,
5508 operand * result, int offr,
5509 int shCount, int sign)
5511 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5512 /* shift right accumulator */
5517 aopPut (AOP (result), "a", offr);
5520 /*-----------------------------------------------------------------*/
5521 /* shiftL1Left2Result - shift left one byte from left to result */
5522 /*-----------------------------------------------------------------*/
5524 shiftL1Left2Result (operand * left, int offl,
5525 operand * result, int offr, int shCount)
5528 l = aopGet (AOP (left), offl, FALSE, FALSE);
5530 /* shift left accumulator */
5532 aopPut (AOP (result), "a", offr);
5535 /*-----------------------------------------------------------------*/
5536 /* movLeft2Result - move byte from left to result */
5537 /*-----------------------------------------------------------------*/
5539 movLeft2Result (operand * left, int offl,
5540 operand * result, int offr, int sign)
5543 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5545 l = aopGet (AOP (left), offl, FALSE, FALSE);
5547 if (*l == '@' && (IS_AOP_PREG (result)))
5549 emitcode ("mov", "a,%s", l);
5550 aopPut (AOP (result), "a", offr);
5555 aopPut (AOP (result), l, offr);
5558 /* MSB sign in acc.7 ! */
5559 if (getDataSize (left) == offl + 1)
5561 emitcode ("mov", "a,%s", l);
5562 aopPut (AOP (result), "a", offr);
5569 /*-----------------------------------------------------------------*/
5570 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5571 /*-----------------------------------------------------------------*/
5575 emitcode ("rrc", "a");
5576 emitcode ("xch", "a,%s", x);
5577 emitcode ("rrc", "a");
5578 emitcode ("xch", "a,%s", x);
5581 /*-----------------------------------------------------------------*/
5582 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5583 /*-----------------------------------------------------------------*/
5587 emitcode ("xch", "a,%s", x);
5588 emitcode ("rlc", "a");
5589 emitcode ("xch", "a,%s", x);
5590 emitcode ("rlc", "a");
5593 /*-----------------------------------------------------------------*/
5594 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5595 /*-----------------------------------------------------------------*/
5599 emitcode ("xch", "a,%s", x);
5600 emitcode ("add", "a,acc");
5601 emitcode ("xch", "a,%s", x);
5602 emitcode ("rlc", "a");
5605 /*-----------------------------------------------------------------*/
5606 /* AccAXLsh - left shift a:x by known count (0..7) */
5607 /*-----------------------------------------------------------------*/
5609 AccAXLsh (char *x, int shCount)
5624 case 5: // AAAAABBB:CCCCCDDD
5626 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5628 emitcode ("anl", "a,#0x%02x",
5629 SLMask[shCount]); // BBB00000:CCCCCDDD
5631 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5633 AccRol (shCount); // DDDCCCCC:BBB00000
5635 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5637 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5639 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5641 emitcode ("anl", "a,#0x%02x",
5642 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5644 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5646 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5649 case 6: // AAAAAABB:CCCCCCDD
5650 emitcode ("anl", "a,#0x%02x",
5651 SRMask[shCount]); // 000000BB:CCCCCCDD
5652 emitcode ("mov", "c,acc.0"); // c = B
5653 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5655 AccAXRrl1 (x); // BCCCCCCD:D000000B
5656 AccAXRrl1 (x); // BBCCCCCC:DD000000
5658 emitcode("rrc","a");
5659 emitcode("xch","a,%s", x);
5660 emitcode("rrc","a");
5661 emitcode("mov","c,acc.0"); //<< get correct bit
5662 emitcode("xch","a,%s", x);
5664 emitcode("rrc","a");
5665 emitcode("xch","a,%s", x);
5666 emitcode("rrc","a");
5667 emitcode("xch","a,%s", x);
5670 case 7: // a:x <<= 7
5672 emitcode ("anl", "a,#0x%02x",
5673 SRMask[shCount]); // 0000000B:CCCCCCCD
5675 emitcode ("mov", "c,acc.0"); // c = B
5677 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5679 AccAXRrl1 (x); // BCCCCCCC:D0000000
5687 /*-----------------------------------------------------------------*/
5688 /* AccAXRsh - right shift a:x known count (0..7) */
5689 /*-----------------------------------------------------------------*/
5691 AccAXRsh (char *x, int shCount)
5699 AccAXRrl1 (x); // 0->a:x
5704 AccAXRrl1 (x); // 0->a:x
5707 AccAXRrl1 (x); // 0->a:x
5712 case 5: // AAAAABBB:CCCCCDDD = a:x
5714 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5716 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5718 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5720 emitcode ("anl", "a,#0x%02x",
5721 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5723 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5725 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5727 emitcode ("anl", "a,#0x%02x",
5728 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5730 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5732 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5734 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5737 case 6: // AABBBBBB:CCDDDDDD
5739 emitcode ("mov", "c,acc.7");
5740 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5742 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5744 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5746 emitcode ("anl", "a,#0x%02x",
5747 SRMask[shCount]); // 000000AA:BBBBBBCC
5750 case 7: // ABBBBBBB:CDDDDDDD
5752 emitcode ("mov", "c,acc.7"); // c = A
5754 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5756 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5758 emitcode ("anl", "a,#0x%02x",
5759 SRMask[shCount]); // 0000000A:BBBBBBBC
5767 /*-----------------------------------------------------------------*/
5768 /* AccAXRshS - right shift signed a:x known count (0..7) */
5769 /*-----------------------------------------------------------------*/
5771 AccAXRshS (char *x, int shCount)
5779 emitcode ("mov", "c,acc.7");
5780 AccAXRrl1 (x); // s->a:x
5784 emitcode ("mov", "c,acc.7");
5785 AccAXRrl1 (x); // s->a:x
5787 emitcode ("mov", "c,acc.7");
5788 AccAXRrl1 (x); // s->a:x
5793 case 5: // AAAAABBB:CCCCCDDD = a:x
5795 tlbl = newiTempLabel (NULL);
5796 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5798 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5800 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5802 emitcode ("anl", "a,#0x%02x",
5803 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5805 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5807 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5809 emitcode ("anl", "a,#0x%02x",
5810 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5812 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5814 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5816 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5818 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5819 emitcode ("orl", "a,#0x%02x",
5820 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5822 emitcode ("", "%05d$:", tlbl->key + 100);
5823 break; // SSSSAAAA:BBBCCCCC
5825 case 6: // AABBBBBB:CCDDDDDD
5827 tlbl = newiTempLabel (NULL);
5828 emitcode ("mov", "c,acc.7");
5829 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5831 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5833 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5835 emitcode ("anl", "a,#0x%02x",
5836 SRMask[shCount]); // 000000AA:BBBBBBCC
5838 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5839 emitcode ("orl", "a,#0x%02x",
5840 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5842 emitcode ("", "%05d$:", tlbl->key + 100);
5844 case 7: // ABBBBBBB:CDDDDDDD
5846 tlbl = newiTempLabel (NULL);
5847 emitcode ("mov", "c,acc.7"); // c = A
5849 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5851 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5853 emitcode ("anl", "a,#0x%02x",
5854 SRMask[shCount]); // 0000000A:BBBBBBBC
5856 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5857 emitcode ("orl", "a,#0x%02x",
5858 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5860 emitcode ("", "%05d$:", tlbl->key + 100);
5867 /*-----------------------------------------------------------------*/
5868 /* shiftL2Left2Result - shift left two bytes from left to result */
5869 /*-----------------------------------------------------------------*/
5871 shiftL2Left2Result (operand * left, int offl,
5872 operand * result, int offr, int shCount)
5874 if (sameRegs (AOP (result), AOP (left)) &&
5875 ((offl + MSB16) == offr))
5877 /* don't crash result[offr] */
5878 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5879 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5883 movLeft2Result (left, offl, result, offr, 0);
5884 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5886 /* ax << shCount (x = lsb(result)) */
5887 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5888 aopPut (AOP (result), "a", offr + MSB16);
5892 /*-----------------------------------------------------------------*/
5893 /* shiftR2Left2Result - shift right two bytes from left to result */
5894 /*-----------------------------------------------------------------*/
5896 shiftR2Left2Result (operand * left, int offl,
5897 operand * result, int offr,
5898 int shCount, int sign)
5900 if (sameRegs (AOP (result), AOP (left)) &&
5901 ((offl + MSB16) == offr))
5903 /* don't crash result[offr] */
5904 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5905 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5909 movLeft2Result (left, offl, result, offr, 0);
5910 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5912 /* a:x >> shCount (x = lsb(result)) */
5914 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5916 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5917 if (getDataSize (result) > 1)
5918 aopPut (AOP (result), "a", offr + MSB16);
5921 /*-----------------------------------------------------------------*/
5922 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5923 /*-----------------------------------------------------------------*/
5925 shiftLLeftOrResult (operand * left, int offl,
5926 operand * result, int offr, int shCount)
5928 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5929 /* shift left accumulator */
5931 /* or with result */
5932 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5933 /* back to result */
5934 aopPut (AOP (result), "a", offr);
5937 /*-----------------------------------------------------------------*/
5938 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5939 /*-----------------------------------------------------------------*/
5941 shiftRLeftOrResult (operand * left, int offl,
5942 operand * result, int offr, int shCount)
5944 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5945 /* shift right accumulator */
5947 /* or with result */
5948 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5949 /* back to result */
5950 aopPut (AOP (result), "a", offr);
5953 /*-----------------------------------------------------------------*/
5954 /* genlshOne - left shift a one byte quantity by known count */
5955 /*-----------------------------------------------------------------*/
5957 genlshOne (operand * result, operand * left, int shCount)
5959 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5962 /*-----------------------------------------------------------------*/
5963 /* genlshTwo - left shift two bytes by known amount != 0 */
5964 /*-----------------------------------------------------------------*/
5966 genlshTwo (operand * result, operand * left, int shCount)
5970 size = getDataSize (result);
5972 /* if shCount >= 8 */
5980 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5982 movLeft2Result (left, LSB, result, MSB16, 0);
5984 aopPut (AOP (result), zero, LSB);
5987 /* 1 <= shCount <= 7 */
5991 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5993 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5997 /*-----------------------------------------------------------------*/
5998 /* shiftLLong - shift left one long from left to result */
5999 /* offl = LSB or MSB16 */
6000 /*-----------------------------------------------------------------*/
6002 shiftLLong (operand * left, operand * result, int offr)
6005 int size = AOP_SIZE (result);
6007 if (size >= LSB + offr)
6009 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6011 emitcode ("add", "a,acc");
6012 if (sameRegs (AOP (left), AOP (result)) &&
6013 size >= MSB16 + offr && offr != LSB)
6014 emitcode ("xch", "a,%s",
6015 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6017 aopPut (AOP (result), "a", LSB + offr);
6020 if (size >= MSB16 + offr)
6022 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6024 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6027 emitcode ("rlc", "a");
6028 if (sameRegs (AOP (left), AOP (result)) &&
6029 size >= MSB24 + offr && offr != LSB)
6030 emitcode ("xch", "a,%s",
6031 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6033 aopPut (AOP (result), "a", MSB16 + offr);
6036 if (size >= MSB24 + offr)
6038 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6040 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6043 emitcode ("rlc", "a");
6044 if (sameRegs (AOP (left), AOP (result)) &&
6045 size >= MSB32 + offr && offr != LSB)
6046 emitcode ("xch", "a,%s",
6047 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6049 aopPut (AOP (result), "a", MSB24 + offr);
6052 if (size > MSB32 + offr)
6054 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6056 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6059 emitcode ("rlc", "a");
6060 aopPut (AOP (result), "a", MSB32 + offr);
6063 aopPut (AOP (result), zero, LSB);
6066 /*-----------------------------------------------------------------*/
6067 /* genlshFour - shift four byte by a known amount != 0 */
6068 /*-----------------------------------------------------------------*/
6070 genlshFour (operand * result, operand * left, int shCount)
6074 size = AOP_SIZE (result);
6076 /* if shifting more that 3 bytes */
6081 /* lowest order of left goes to the highest
6082 order of the destination */
6083 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6085 movLeft2Result (left, LSB, result, MSB32, 0);
6086 aopPut (AOP (result), zero, LSB);
6087 aopPut (AOP (result), zero, MSB16);
6088 aopPut (AOP (result), zero, MSB24);
6092 /* more than two bytes */
6093 else if (shCount >= 16)
6095 /* lower order two bytes goes to higher order two bytes */
6097 /* if some more remaining */
6099 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6102 movLeft2Result (left, MSB16, result, MSB32, 0);
6103 movLeft2Result (left, LSB, result, MSB24, 0);
6105 aopPut (AOP (result), zero, MSB16);
6106 aopPut (AOP (result), zero, LSB);
6110 /* if more than 1 byte */
6111 else if (shCount >= 8)
6113 /* lower order three bytes goes to higher order three bytes */
6118 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6120 movLeft2Result (left, LSB, result, MSB16, 0);
6126 movLeft2Result (left, MSB24, result, MSB32, 0);
6127 movLeft2Result (left, MSB16, result, MSB24, 0);
6128 movLeft2Result (left, LSB, result, MSB16, 0);
6129 aopPut (AOP (result), zero, LSB);
6131 else if (shCount == 1)
6132 shiftLLong (left, result, MSB16);
6135 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6136 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6137 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6138 aopPut (AOP (result), zero, LSB);
6143 /* 1 <= shCount <= 7 */
6144 else if (shCount <= 2)
6146 shiftLLong (left, result, LSB);
6148 shiftLLong (result, result, LSB);
6150 /* 3 <= shCount <= 7, optimize */
6153 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6154 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6155 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6159 /*-----------------------------------------------------------------*/
6160 /* genLeftShiftLiteral - left shifting by known count */
6161 /*-----------------------------------------------------------------*/
6163 genLeftShiftLiteral (operand * left,
6168 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6171 freeAsmop (right, NULL, ic, TRUE);
6173 aopOp (left, ic, FALSE);
6174 aopOp (result, ic, FALSE);
6176 size = getSize (operandType (result));
6179 emitcode ("; shift left ", "result %d, left %d", size,
6183 /* I suppose that the left size >= result size */
6188 movLeft2Result (left, size, result, size, 0);
6192 else if (shCount >= (size * 8))
6194 aopPut (AOP (result), zero, size);
6200 genlshOne (result, left, shCount);
6204 genlshTwo (result, left, shCount);
6208 genlshFour (result, left, shCount);
6211 fprintf(stderr, "*** ack! mystery literal shift!\n");
6215 freeAsmop (left, NULL, ic, TRUE);
6216 freeAsmop (result, NULL, ic, TRUE);
6219 /*-----------------------------------------------------------------*/
6220 /* genLeftShift - generates code for left shifting */
6221 /*-----------------------------------------------------------------*/
6223 genLeftShift (iCode * ic)
6225 operand *left, *right, *result;
6228 symbol *tlbl, *tlbl1;
6230 right = IC_RIGHT (ic);
6231 left = IC_LEFT (ic);
6232 result = IC_RESULT (ic);
6234 aopOp (right, ic, FALSE);
6236 /* if the shift count is known then do it
6237 as efficiently as possible */
6238 if (AOP_TYPE (right) == AOP_LIT)
6240 genLeftShiftLiteral (left, right, result, ic);
6244 /* shift count is unknown then we have to form
6245 a loop get the loop count in B : Note: we take
6246 only the lower order byte since shifting
6247 more that 32 bits make no sense anyway, ( the
6248 largest size of an object can be only 32 bits ) */
6250 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6251 emitcode ("inc", "b");
6252 freeAsmop (right, NULL, ic, TRUE);
6253 aopOp (left, ic, FALSE);
6254 aopOp (result, ic, FALSE);
6256 /* now move the left to the result if they are not the
6258 if (!sameRegs (AOP (left), AOP (result)) &&
6259 AOP_SIZE (result) > 1)
6262 size = AOP_SIZE (result);
6266 l = aopGet (AOP (left), offset, FALSE, TRUE);
6267 if (*l == '@' && (IS_AOP_PREG (result)))
6270 emitcode ("mov", "a,%s", l);
6271 aopPut (AOP (result), "a", offset);
6274 aopPut (AOP (result), l, offset);
6279 tlbl = newiTempLabel (NULL);
6280 size = AOP_SIZE (result);
6282 tlbl1 = newiTempLabel (NULL);
6284 /* if it is only one byte then */
6287 symbol *tlbl1 = newiTempLabel (NULL);
6289 l = aopGet (AOP (left), 0, FALSE, FALSE);
6291 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6292 emitcode ("", "%05d$:", tlbl->key + 100);
6293 emitcode ("add", "a,acc");
6294 emitcode ("", "%05d$:", tlbl1->key + 100);
6295 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6296 aopPut (AOP (result), "a", 0);
6300 reAdjustPreg (AOP (result));
6302 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6303 emitcode ("", "%05d$:", tlbl->key + 100);
6304 l = aopGet (AOP (result), offset, FALSE, FALSE);
6306 emitcode ("add", "a,acc");
6307 aopPut (AOP (result), "a", offset++);
6310 l = aopGet (AOP (result), offset, FALSE, FALSE);
6312 emitcode ("rlc", "a");
6313 aopPut (AOP (result), "a", offset++);
6315 reAdjustPreg (AOP (result));
6317 emitcode ("", "%05d$:", tlbl1->key + 100);
6318 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6320 freeAsmop (left, NULL, ic, TRUE);
6321 freeAsmop (result, NULL, ic, TRUE);
6324 /*-----------------------------------------------------------------*/
6325 /* genrshOne - right shift a one byte quantity by known count */
6326 /*-----------------------------------------------------------------*/
6328 genrshOne (operand * result, operand * left,
6329 int shCount, int sign)
6331 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6334 /*-----------------------------------------------------------------*/
6335 /* genrshTwo - right shift two bytes by known amount != 0 */
6336 /*-----------------------------------------------------------------*/
6338 genrshTwo (operand * result, operand * left,
6339 int shCount, int sign)
6341 /* if shCount >= 8 */
6346 shiftR1Left2Result (left, MSB16, result, LSB,
6349 movLeft2Result (left, MSB16, result, LSB, sign);
6350 addSign (result, MSB16, sign);
6353 /* 1 <= shCount <= 7 */
6355 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6358 /*-----------------------------------------------------------------*/
6359 /* shiftRLong - shift right one long from left to result */
6360 /* offl = LSB or MSB16 */
6361 /*-----------------------------------------------------------------*/
6363 shiftRLong (operand * left, int offl,
6364 operand * result, int sign)
6366 int isSameRegs=sameRegs(AOP(left),AOP(result));
6368 if (isSameRegs && offl>1) {
6369 // we are in big trouble, but this shouldn't happen
6370 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6373 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6378 emitcode ("rlc", "a");
6379 emitcode ("subb", "a,acc");
6380 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6382 aopPut (AOP(result), zero, MSB32);
6387 emitcode ("clr", "c");
6389 emitcode ("mov", "c,acc.7");
6392 emitcode ("rrc", "a");
6394 if (isSameRegs && offl==MSB16) {
6395 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6397 aopPut (AOP (result), "a", MSB32);
6398 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6401 emitcode ("rrc", "a");
6402 if (isSameRegs && offl==1) {
6403 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6405 aopPut (AOP (result), "a", MSB24);
6406 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6408 emitcode ("rrc", "a");
6409 aopPut (AOP (result), "a", MSB16 - offl);
6413 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6414 emitcode ("rrc", "a");
6415 aopPut (AOP (result), "a", LSB);
6419 /*-----------------------------------------------------------------*/
6420 /* genrshFour - shift four byte by a known amount != 0 */
6421 /*-----------------------------------------------------------------*/
6423 genrshFour (operand * result, operand * left,
6424 int shCount, int sign)
6426 /* if shifting more that 3 bytes */
6431 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6433 movLeft2Result (left, MSB32, result, LSB, sign);
6434 addSign (result, MSB16, sign);
6436 else if (shCount >= 16)
6440 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6443 movLeft2Result (left, MSB24, result, LSB, 0);
6444 movLeft2Result (left, MSB32, result, MSB16, sign);
6446 addSign (result, MSB24, sign);
6448 else if (shCount >= 8)
6452 shiftRLong (left, MSB16, result, sign);
6453 else if (shCount == 0)
6455 movLeft2Result (left, MSB16, result, LSB, 0);
6456 movLeft2Result (left, MSB24, result, MSB16, 0);
6457 movLeft2Result (left, MSB32, result, MSB24, sign);
6458 addSign (result, MSB32, sign);
6462 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6463 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6464 /* the last shift is signed */
6465 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6466 addSign (result, MSB32, sign);
6470 { /* 1 <= shCount <= 7 */
6473 shiftRLong (left, LSB, result, sign);
6475 shiftRLong (result, LSB, result, sign);
6479 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6480 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6481 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6486 /*-----------------------------------------------------------------*/
6487 /* genRightShiftLiteral - right shifting by known count */
6488 /*-----------------------------------------------------------------*/
6490 genRightShiftLiteral (operand * left,
6496 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6499 freeAsmop (right, NULL, ic, TRUE);
6501 aopOp (left, ic, FALSE);
6502 aopOp (result, ic, FALSE);
6505 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6509 size = getDataSize (left);
6510 /* test the LEFT size !!! */
6512 /* I suppose that the left size >= result size */
6515 size = getDataSize (result);
6517 movLeft2Result (left, size, result, size, 0);
6520 else if (shCount >= (size * 8))
6523 /* get sign in acc.7 */
6524 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6525 addSign (result, LSB, sign);
6532 genrshOne (result, left, shCount, sign);
6536 genrshTwo (result, left, shCount, sign);
6540 genrshFour (result, left, shCount, sign);
6546 freeAsmop (left, NULL, ic, TRUE);
6547 freeAsmop (result, NULL, ic, TRUE);
6551 /*-----------------------------------------------------------------*/
6552 /* genSignedRightShift - right shift of signed number */
6553 /*-----------------------------------------------------------------*/
6555 genSignedRightShift (iCode * ic)
6557 operand *right, *left, *result;
6560 symbol *tlbl, *tlbl1;
6562 /* we do it the hard way put the shift count in b
6563 and loop thru preserving the sign */
6565 right = IC_RIGHT (ic);
6566 left = IC_LEFT (ic);
6567 result = IC_RESULT (ic);
6569 aopOp (right, ic, FALSE);
6572 if (AOP_TYPE (right) == AOP_LIT)
6574 genRightShiftLiteral (left, right, result, ic, 1);
6577 /* shift count is unknown then we have to form
6578 a loop get the loop count in B : Note: we take
6579 only the lower order byte since shifting
6580 more that 32 bits make no sense anyway, ( the
6581 largest size of an object can be only 32 bits ) */
6583 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6584 emitcode ("inc", "b");
6585 freeAsmop (right, NULL, ic, TRUE);
6586 aopOp (left, ic, FALSE);
6587 aopOp (result, ic, FALSE);
6589 /* now move the left to the result if they are not the
6591 if (!sameRegs (AOP (left), AOP (result)) &&
6592 AOP_SIZE (result) > 1)
6595 size = AOP_SIZE (result);
6599 l = aopGet (AOP (left), offset, FALSE, TRUE);
6600 if (*l == '@' && IS_AOP_PREG (result))
6603 emitcode ("mov", "a,%s", l);
6604 aopPut (AOP (result), "a", offset);
6607 aopPut (AOP (result), l, offset);
6612 /* mov the highest order bit to OVR */
6613 tlbl = newiTempLabel (NULL);
6614 tlbl1 = newiTempLabel (NULL);
6616 size = AOP_SIZE (result);
6618 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6619 emitcode ("rlc", "a");
6620 emitcode ("mov", "ov,c");
6621 /* if it is only one byte then */
6624 l = aopGet (AOP (left), 0, FALSE, FALSE);
6626 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6627 emitcode ("", "%05d$:", tlbl->key + 100);
6628 emitcode ("mov", "c,ov");
6629 emitcode ("rrc", "a");
6630 emitcode ("", "%05d$:", tlbl1->key + 100);
6631 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6632 aopPut (AOP (result), "a", 0);
6636 reAdjustPreg (AOP (result));
6637 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6638 emitcode ("", "%05d$:", tlbl->key + 100);
6639 emitcode ("mov", "c,ov");
6642 l = aopGet (AOP (result), offset, FALSE, FALSE);
6644 emitcode ("rrc", "a");
6645 aopPut (AOP (result), "a", offset--);
6647 reAdjustPreg (AOP (result));
6648 emitcode ("", "%05d$:", tlbl1->key + 100);
6649 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6652 freeAsmop (left, NULL, ic, TRUE);
6653 freeAsmop (result, NULL, ic, TRUE);
6656 /*-----------------------------------------------------------------*/
6657 /* genRightShift - generate code for right shifting */
6658 /*-----------------------------------------------------------------*/
6660 genRightShift (iCode * ic)
6662 operand *right, *left, *result;
6666 symbol *tlbl, *tlbl1;
6668 /* if signed then we do it the hard way preserve the
6669 sign bit moving it inwards */
6670 retype = getSpec (operandType (IC_RESULT (ic)));
6672 if (!SPEC_USIGN (retype))
6674 genSignedRightShift (ic);
6678 /* signed & unsigned types are treated the same : i.e. the
6679 signed is NOT propagated inwards : quoting from the
6680 ANSI - standard : "for E1 >> E2, is equivalent to division
6681 by 2**E2 if unsigned or if it has a non-negative value,
6682 otherwise the result is implementation defined ", MY definition
6683 is that the sign does not get propagated */
6685 right = IC_RIGHT (ic);
6686 left = IC_LEFT (ic);
6687 result = IC_RESULT (ic);
6689 aopOp (right, ic, FALSE);
6691 /* if the shift count is known then do it
6692 as efficiently as possible */
6693 if (AOP_TYPE (right) == AOP_LIT)
6695 genRightShiftLiteral (left, right, result, ic, 0);
6699 /* shift count is unknown then we have to form
6700 a loop get the loop count in B : Note: we take
6701 only the lower order byte since shifting
6702 more that 32 bits make no sense anyway, ( the
6703 largest size of an object can be only 32 bits ) */
6705 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6706 emitcode ("inc", "b");
6707 freeAsmop (right, NULL, ic, TRUE);
6708 aopOp (left, ic, FALSE);
6709 aopOp (result, ic, FALSE);
6711 /* now move the left to the result if they are not the
6713 if (!sameRegs (AOP (left), AOP (result)) &&
6714 AOP_SIZE (result) > 1)
6717 size = AOP_SIZE (result);
6721 l = aopGet (AOP (left), offset, FALSE, TRUE);
6722 if (*l == '@' && IS_AOP_PREG (result))
6725 emitcode ("mov", "a,%s", l);
6726 aopPut (AOP (result), "a", offset);
6729 aopPut (AOP (result), l, offset);
6734 tlbl = newiTempLabel (NULL);
6735 tlbl1 = newiTempLabel (NULL);
6736 size = AOP_SIZE (result);
6739 /* if it is only one byte then */
6742 l = aopGet (AOP (left), 0, FALSE, FALSE);
6744 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6745 emitcode ("", "%05d$:", tlbl->key + 100);
6747 emitcode ("rrc", "a");
6748 emitcode ("", "%05d$:", tlbl1->key + 100);
6749 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6750 aopPut (AOP (result), "a", 0);
6754 reAdjustPreg (AOP (result));
6755 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6756 emitcode ("", "%05d$:", tlbl->key + 100);
6760 l = aopGet (AOP (result), offset, FALSE, FALSE);
6762 emitcode ("rrc", "a");
6763 aopPut (AOP (result), "a", offset--);
6765 reAdjustPreg (AOP (result));
6767 emitcode ("", "%05d$:", tlbl1->key + 100);
6768 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6771 freeAsmop (left, NULL, ic, TRUE);
6772 freeAsmop (result, NULL, ic, TRUE);
6775 /*-----------------------------------------------------------------*/
6776 /* genUnpackBits - generates code for unpacking bits */
6777 /*-----------------------------------------------------------------*/
6779 genUnpackBits (operand * result, char *rname, int ptype)
6787 etype = getSpec (operandType (result));
6788 rsize = getSize (operandType (result));
6789 /* read the first byte */
6795 emitcode ("mov", "a,@%s", rname);
6799 emitcode ("movx", "a,@%s", rname);
6803 emitcode ("movx", "a,@dptr");
6807 emitcode ("clr", "a");
6808 emitcode ("movc", "a,@a+dptr");
6812 emitcode ("lcall", "__gptrget");
6816 rlen = SPEC_BLEN (etype);
6818 /* if we have bitdisplacement then it fits */
6819 /* into this byte completely or if length is */
6820 /* less than a byte */
6821 if ((shCnt = SPEC_BSTR (etype)) ||
6822 (SPEC_BLEN (etype) <= 8))
6825 /* shift right acc */
6828 emitcode ("anl", "a,#0x%02x",
6829 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6830 aopPut (AOP (result), "a", offset++);
6834 /* bit field did not fit in a byte */
6835 aopPut (AOP (result), "a", offset++);
6844 emitcode ("inc", "%s", rname);
6845 emitcode ("mov", "a,@%s", rname);
6849 emitcode ("inc", "%s", rname);
6850 emitcode ("movx", "a,@%s", rname);
6854 emitcode ("inc", "dptr");
6855 emitcode ("movx", "a,@dptr");
6859 emitcode ("clr", "a");
6860 emitcode ("inc", "dptr");
6861 emitcode ("movc", "a,@a+dptr");
6865 emitcode ("inc", "dptr");
6866 emitcode ("lcall", "__gptrget");
6871 /* if we are done */
6875 aopPut (AOP (result), "a", offset++);
6881 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6883 aopPut (AOP (result), "a", offset++);
6891 aopPut (AOP (result), zero, offset++);
6897 /*-----------------------------------------------------------------*/
6898 /* genDataPointerGet - generates code when ptr offset is known */
6899 /*-----------------------------------------------------------------*/
6901 genDataPointerGet (operand * left,
6907 int size, offset = 0;
6908 aopOp (result, ic, TRUE);
6910 /* get the string representation of the name */
6911 l = aopGet (AOP (left), 0, FALSE, TRUE);
6912 size = AOP_SIZE (result);
6916 sprintf (buffer, "(%s + %d)", l + 1, offset);
6918 sprintf (buffer, "%s", l + 1);
6919 aopPut (AOP (result), buffer, offset++);
6922 freeAsmop (left, NULL, ic, TRUE);
6923 freeAsmop (result, NULL, ic, TRUE);
6926 /*-----------------------------------------------------------------*/
6927 /* genNearPointerGet - emitcode for near pointer fetch */
6928 /*-----------------------------------------------------------------*/
6930 genNearPointerGet (operand * left,
6938 sym_link *rtype, *retype;
6939 sym_link *ltype = operandType (left);
6942 rtype = operandType (result);
6943 retype = getSpec (rtype);
6945 aopOp (left, ic, FALSE);
6947 /* if left is rematerialisable and
6948 result is not bit variable type and
6949 the left is pointer to data space i.e
6950 lower 128 bytes of space */
6951 if (AOP_TYPE (left) == AOP_IMMD &&
6952 !IS_BITVAR (retype) &&
6953 DCL_TYPE (ltype) == POINTER)
6955 genDataPointerGet (left, result, ic);
6959 /* if the value is already in a pointer register
6960 then don't need anything more */
6961 if (!AOP_INPREG (AOP (left)))
6963 /* otherwise get a free pointer register */
6965 preg = getFreePtr (ic, &aop, FALSE);
6966 emitcode ("mov", "%s,%s",
6968 aopGet (AOP (left), 0, FALSE, TRUE));
6972 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6974 //aopOp (result, ic, FALSE);
6975 aopOp (result, ic, result?TRUE:FALSE);
6977 /* if bitfield then unpack the bits */
6978 if (IS_BITVAR (retype))
6979 genUnpackBits (result, rname, POINTER);
6982 /* we have can just get the values */
6983 int size = AOP_SIZE (result);
6988 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6991 emitcode ("mov", "a,@%s", rname);
6992 aopPut (AOP (result), "a", offset);
6996 sprintf (buffer, "@%s", rname);
6997 aopPut (AOP (result), buffer, offset);
7001 emitcode ("inc", "%s", rname);
7005 /* now some housekeeping stuff */
7006 if (aop) /* we had to allocate for this iCode */
7008 if (pi) { /* post increment present */
7009 aopPut(AOP ( left ),rname,0);
7011 freeAsmop (NULL, aop, ic, TRUE);
7015 /* we did not allocate which means left
7016 already in a pointer register, then
7017 if size > 0 && this could be used again
7018 we have to point it back to where it
7020 if ((AOP_SIZE (result) > 1 &&
7021 !OP_SYMBOL (left)->remat &&
7022 (OP_SYMBOL (left)->liveTo > ic->seq ||
7026 int size = AOP_SIZE (result) - 1;
7028 emitcode ("dec", "%s", rname);
7033 freeAsmop (left, NULL, ic, TRUE);
7034 freeAsmop (result, NULL, ic, TRUE);
7035 if (pi) pi->generated = 1;
7038 /*-----------------------------------------------------------------*/
7039 /* genPagedPointerGet - emitcode for paged pointer fetch */
7040 /*-----------------------------------------------------------------*/
7042 genPagedPointerGet (operand * left,
7050 sym_link *rtype, *retype;
7052 rtype = operandType (result);
7053 retype = getSpec (rtype);
7055 aopOp (left, ic, FALSE);
7057 /* if the value is already in a pointer register
7058 then don't need anything more */
7059 if (!AOP_INPREG (AOP (left)))
7061 /* otherwise get a free pointer register */
7063 preg = getFreePtr (ic, &aop, FALSE);
7064 emitcode ("mov", "%s,%s",
7066 aopGet (AOP (left), 0, FALSE, TRUE));
7070 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7072 aopOp (result, ic, FALSE);
7074 /* if bitfield then unpack the bits */
7075 if (IS_BITVAR (retype))
7076 genUnpackBits (result, rname, PPOINTER);
7079 /* we have can just get the values */
7080 int size = AOP_SIZE (result);
7086 emitcode ("movx", "a,@%s", rname);
7087 aopPut (AOP (result), "a", offset);
7092 emitcode ("inc", "%s", rname);
7096 /* now some housekeeping stuff */
7097 if (aop) /* we had to allocate for this iCode */
7099 if (pi) aopPut ( AOP (left), rname, 0);
7100 freeAsmop (NULL, aop, ic, TRUE);
7104 /* we did not allocate which means left
7105 already in a pointer register, then
7106 if size > 0 && this could be used again
7107 we have to point it back to where it
7109 if ((AOP_SIZE (result) > 1 &&
7110 !OP_SYMBOL (left)->remat &&
7111 (OP_SYMBOL (left)->liveTo > ic->seq ||
7115 int size = AOP_SIZE (result) - 1;
7117 emitcode ("dec", "%s", rname);
7122 freeAsmop (left, NULL, ic, TRUE);
7123 freeAsmop (result, NULL, ic, TRUE);
7124 if (pi) pi->generated = 1;
7128 /*-----------------------------------------------------------------*/
7129 /* genFarPointerGet - gget value from far space */
7130 /*-----------------------------------------------------------------*/
7132 genFarPointerGet (operand * left,
7133 operand * result, iCode * ic, iCode * pi)
7136 sym_link *retype = getSpec (operandType (result));
7138 aopOp (left, ic, FALSE);
7140 /* if the operand is already in dptr
7141 then we do nothing else we move the value to dptr */
7142 if (AOP_TYPE (left) != AOP_STR)
7144 /* if this is remateriazable */
7145 if (AOP_TYPE (left) == AOP_IMMD)
7146 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7148 { /* we need to get it byte by byte */
7149 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7150 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7153 /* so dptr know contains the address */
7154 aopOp (result, ic, FALSE);
7156 /* if bit then unpack */
7157 if (IS_BITVAR (retype))
7158 genUnpackBits (result, "dptr", FPOINTER);
7161 size = AOP_SIZE (result);
7166 emitcode ("movx", "a,@dptr");
7167 aopPut (AOP (result), "a", offset++);
7169 emitcode ("inc", "dptr");
7173 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7174 aopPut ( AOP (left), "dpl", 0);
7175 aopPut ( AOP (left), "dph", 1);
7178 freeAsmop (left, NULL, ic, TRUE);
7179 freeAsmop (result, NULL, ic, TRUE);
7182 /*-----------------------------------------------------------------*/
7183 /* genCodePointerGet - gget value from code space */
7184 /*-----------------------------------------------------------------*/
7186 genCodePointerGet (operand * left,
7187 operand * result, iCode * ic, iCode *pi)
7190 sym_link *retype = getSpec (operandType (result));
7192 aopOp (left, ic, FALSE);
7194 /* if the operand is already in dptr
7195 then we do nothing else we move the value to dptr */
7196 if (AOP_TYPE (left) != AOP_STR)
7198 /* if this is remateriazable */
7199 if (AOP_TYPE (left) == AOP_IMMD)
7200 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7202 { /* we need to get it byte by byte */
7203 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7204 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7207 /* so dptr know contains the address */
7208 aopOp (result, ic, FALSE);
7210 /* if bit then unpack */
7211 if (IS_BITVAR (retype))
7212 genUnpackBits (result, "dptr", CPOINTER);
7215 size = AOP_SIZE (result);
7220 emitcode ("clr", "a");
7221 emitcode ("movc", "a,@a+dptr");
7222 aopPut (AOP (result), "a", offset++);
7224 emitcode ("inc", "dptr");
7228 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7229 aopPut ( AOP (left), "dpl", 0);
7230 aopPut ( AOP (left), "dph", 1);
7233 freeAsmop (left, NULL, ic, TRUE);
7234 freeAsmop (result, NULL, ic, TRUE);
7237 /*-----------------------------------------------------------------*/
7238 /* genGenPointerGet - gget value from generic pointer space */
7239 /*-----------------------------------------------------------------*/
7241 genGenPointerGet (operand * left,
7242 operand * result, iCode * ic, iCode *pi)
7245 sym_link *retype = getSpec (operandType (result));
7247 aopOp (left, ic, FALSE);
7249 /* if the operand is already in dptr
7250 then we do nothing else we move the value to dptr */
7251 if (AOP_TYPE (left) != AOP_STR)
7253 /* if this is remateriazable */
7254 if (AOP_TYPE (left) == AOP_IMMD)
7256 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7257 emitcode ("mov", "b,#%d", pointerCode (retype));
7260 { /* we need to get it byte by byte */
7261 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7262 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7263 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7266 /* so dptr know contains the address */
7267 aopOp (result, ic, FALSE);
7269 /* if bit then unpack */
7270 if (IS_BITVAR (retype))
7271 genUnpackBits (result, "dptr", GPOINTER);
7274 size = AOP_SIZE (result);
7279 emitcode ("lcall", "__gptrget");
7280 aopPut (AOP (result), "a", offset++);
7282 emitcode ("inc", "dptr");
7286 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7287 aopPut ( AOP (left), "dpl", 0);
7288 aopPut ( AOP (left), "dph", 1);
7291 freeAsmop (left, NULL, ic, TRUE);
7292 freeAsmop (result, NULL, ic, TRUE);
7295 /*-----------------------------------------------------------------*/
7296 /* genPointerGet - generate code for pointer get */
7297 /*-----------------------------------------------------------------*/
7299 genPointerGet (iCode * ic, iCode *pi)
7301 operand *left, *result;
7302 sym_link *type, *etype;
7305 left = IC_LEFT (ic);
7306 result = IC_RESULT (ic);
7308 /* depending on the type of pointer we need to
7309 move it to the correct pointer register */
7310 type = operandType (left);
7311 etype = getSpec (type);
7312 /* if left is of type of pointer then it is simple */
7313 if (IS_PTR (type) && !IS_FUNC (type->next))
7314 p_type = DCL_TYPE (type);
7317 /* we have to go by the storage class */
7318 p_type = PTR_TYPE (SPEC_OCLS (etype));
7321 /* now that we have the pointer type we assign
7322 the pointer values */
7328 genNearPointerGet (left, result, ic, pi);
7332 genPagedPointerGet (left, result, ic, pi);
7336 genFarPointerGet (left, result, ic, pi);
7340 genCodePointerGet (left, result, ic, pi);
7344 genGenPointerGet (left, result, ic, pi);
7350 /*-----------------------------------------------------------------*/
7351 /* genPackBits - generates code for packed bit storage */
7352 /*-----------------------------------------------------------------*/
7354 genPackBits (sym_link * etype,
7356 char *rname, int p_type)
7364 blen = SPEC_BLEN (etype);
7365 bstr = SPEC_BSTR (etype);
7367 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7370 /* if the bit lenth is less than or */
7371 /* it exactly fits a byte then */
7372 if (SPEC_BLEN (etype) <= 8)
7374 shCount = SPEC_BSTR (etype);
7376 /* shift left acc */
7379 if (SPEC_BLEN (etype) < 8)
7380 { /* if smaller than a byte */
7386 emitcode ("mov", "b,a");
7387 emitcode ("mov", "a,@%s", rname);
7391 emitcode ("mov", "b,a");
7392 emitcode ("movx", "a,@dptr");
7396 emitcode ("push", "b");
7397 emitcode ("push", "acc");
7398 emitcode ("lcall", "__gptrget");
7399 emitcode ("pop", "b");
7403 emitcode ("anl", "a,#0x%02x", (unsigned char)
7404 ((unsigned char) (0xFF << (blen + bstr)) |
7405 (unsigned char) (0xFF >> (8 - bstr))));
7406 emitcode ("orl", "a,b");
7407 if (p_type == GPOINTER)
7408 emitcode ("pop", "b");
7415 emitcode ("mov", "@%s,a", rname);
7419 emitcode ("movx", "@dptr,a");
7423 emitcode ("lcall", "__gptrput");
7428 if (SPEC_BLEN (etype) <= 8)
7431 emitcode ("inc", "%s", rname);
7432 rLen = SPEC_BLEN (etype);
7434 /* now generate for lengths greater than one byte */
7438 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7450 emitcode ("mov", "@%s,a", rname);
7453 emitcode ("mov", "@%s,%s", rname, l);
7458 emitcode ("movx", "@dptr,a");
7463 emitcode ("lcall", "__gptrput");
7466 emitcode ("inc", "%s", rname);
7471 /* last last was not complete */
7474 /* save the byte & read byte */
7478 emitcode ("mov", "b,a");
7479 emitcode ("mov", "a,@%s", rname);
7483 emitcode ("mov", "b,a");
7484 emitcode ("movx", "a,@dptr");
7488 emitcode ("push", "b");
7489 emitcode ("push", "acc");
7490 emitcode ("lcall", "__gptrget");
7491 emitcode ("pop", "b");
7495 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7496 emitcode ("orl", "a,b");
7499 if (p_type == GPOINTER)
7500 emitcode ("pop", "b");
7506 emitcode ("mov", "@%s,a", rname);
7510 emitcode ("movx", "@dptr,a");
7514 emitcode ("lcall", "__gptrput");
7518 /*-----------------------------------------------------------------*/
7519 /* genDataPointerSet - remat pointer to data space */
7520 /*-----------------------------------------------------------------*/
7522 genDataPointerSet (operand * right,
7526 int size, offset = 0;
7527 char *l, buffer[256];
7529 aopOp (right, ic, FALSE);
7531 l = aopGet (AOP (result), 0, FALSE, TRUE);
7532 size = AOP_SIZE (right);
7536 sprintf (buffer, "(%s + %d)", l + 1, offset);
7538 sprintf (buffer, "%s", l + 1);
7539 emitcode ("mov", "%s,%s", buffer,
7540 aopGet (AOP (right), offset++, FALSE, FALSE));
7543 freeAsmop (right, NULL, ic, TRUE);
7544 freeAsmop (result, NULL, ic, TRUE);
7547 /*-----------------------------------------------------------------*/
7548 /* genNearPointerSet - emitcode for near pointer put */
7549 /*-----------------------------------------------------------------*/
7551 genNearPointerSet (operand * right,
7559 sym_link *retype, *letype;
7560 sym_link *ptype = operandType (result);
7562 retype = getSpec (operandType (right));
7563 letype = getSpec (ptype);
7564 aopOp (result, ic, FALSE);
7566 /* if the result is rematerializable &
7567 in data space & not a bit variable */
7568 if (AOP_TYPE (result) == AOP_IMMD &&
7569 DCL_TYPE (ptype) == POINTER &&
7570 !IS_BITVAR (retype) &&
7571 !IS_BITVAR (letype))
7573 genDataPointerSet (right, result, ic);
7577 /* if the value is already in a pointer register
7578 then don't need anything more */
7579 if (!AOP_INPREG (AOP (result)))
7581 /* otherwise get a free pointer register */
7583 preg = getFreePtr (ic, &aop, FALSE);
7584 emitcode ("mov", "%s,%s",
7586 aopGet (AOP (result), 0, FALSE, TRUE));
7590 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7592 aopOp (right, ic, FALSE);
7594 /* if bitfield then unpack the bits */
7595 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7596 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7599 /* we have can just get the values */
7600 int size = AOP_SIZE (right);
7605 l = aopGet (AOP (right), offset, FALSE, TRUE);
7609 emitcode ("mov", "@%s,a", rname);
7612 emitcode ("mov", "@%s,%s", rname, l);
7614 emitcode ("inc", "%s", rname);
7619 /* now some housekeeping stuff */
7620 if (aop) /* we had to allocate for this iCode */
7622 if (pi) aopPut (AOP (result),rname,0);
7623 freeAsmop (NULL, aop, ic, TRUE);
7627 /* we did not allocate which means left
7628 already in a pointer register, then
7629 if size > 0 && this could be used again
7630 we have to point it back to where it
7632 if ((AOP_SIZE (right) > 1 &&
7633 !OP_SYMBOL (result)->remat &&
7634 (OP_SYMBOL (result)->liveTo > ic->seq ||
7638 int size = AOP_SIZE (right) - 1;
7640 emitcode ("dec", "%s", rname);
7645 if (pi) pi->generated = 1;
7646 freeAsmop (result, NULL, ic, TRUE);
7647 freeAsmop (right, NULL, ic, TRUE);
7650 /*-----------------------------------------------------------------*/
7651 /* genPagedPointerSet - emitcode for Paged pointer put */
7652 /*-----------------------------------------------------------------*/
7654 genPagedPointerSet (operand * right,
7662 sym_link *retype, *letype;
7664 retype = getSpec (operandType (right));
7665 letype = getSpec (operandType (result));
7667 aopOp (result, ic, FALSE);
7669 /* if the value is already in a pointer register
7670 then don't need anything more */
7671 if (!AOP_INPREG (AOP (result)))
7673 /* otherwise get a free pointer register */
7675 preg = getFreePtr (ic, &aop, FALSE);
7676 emitcode ("mov", "%s,%s",
7678 aopGet (AOP (result), 0, FALSE, TRUE));
7682 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7684 aopOp (right, ic, FALSE);
7686 /* if bitfield then unpack the bits */
7687 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7688 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7691 /* we have can just get the values */
7692 int size = AOP_SIZE (right);
7697 l = aopGet (AOP (right), offset, FALSE, TRUE);
7700 emitcode ("movx", "@%s,a", rname);
7703 emitcode ("inc", "%s", rname);
7709 /* now some housekeeping stuff */
7710 if (aop) /* we had to allocate for this iCode */
7712 if (pi) aopPut (AOP (result),rname,0);
7713 freeAsmop (NULL, aop, ic, TRUE);
7717 /* we did not allocate which means left
7718 already in a pointer register, then
7719 if size > 0 && this could be used again
7720 we have to point it back to where it
7722 if (AOP_SIZE (right) > 1 &&
7723 !OP_SYMBOL (result)->remat &&
7724 (OP_SYMBOL (result)->liveTo > ic->seq ||
7727 int size = AOP_SIZE (right) - 1;
7729 emitcode ("dec", "%s", rname);
7734 if (pi) pi->generated = 1;
7735 freeAsmop (result, NULL, ic, TRUE);
7736 freeAsmop (right, NULL, ic, TRUE);
7741 /*-----------------------------------------------------------------*/
7742 /* genFarPointerSet - set value from far space */
7743 /*-----------------------------------------------------------------*/
7745 genFarPointerSet (operand * right,
7746 operand * result, iCode * ic, iCode * pi)
7749 sym_link *retype = getSpec (operandType (right));
7750 sym_link *letype = getSpec (operandType (result));
7751 aopOp (result, ic, FALSE);
7753 /* if the operand is already in dptr
7754 then we do nothing else we move the value to dptr */
7755 if (AOP_TYPE (result) != AOP_STR)
7757 /* if this is remateriazable */
7758 if (AOP_TYPE (result) == AOP_IMMD)
7759 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7761 { /* we need to get it byte by byte */
7762 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7763 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7766 /* so dptr know contains the address */
7767 aopOp (right, ic, FALSE);
7769 /* if bit then unpack */
7770 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7771 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7774 size = AOP_SIZE (right);
7779 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7781 emitcode ("movx", "@dptr,a");
7783 emitcode ("inc", "dptr");
7786 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7787 aopPut (AOP(result),"dpl",0);
7788 aopPut (AOP(result),"dph",1);
7791 freeAsmop (result, NULL, ic, TRUE);
7792 freeAsmop (right, NULL, ic, TRUE);
7795 /*-----------------------------------------------------------------*/
7796 /* genGenPointerSet - set value from generic pointer space */
7797 /*-----------------------------------------------------------------*/
7799 genGenPointerSet (operand * right,
7800 operand * result, iCode * ic, iCode * pi)
7803 sym_link *retype = getSpec (operandType (right));
7804 sym_link *letype = getSpec (operandType (result));
7806 aopOp (result, ic, FALSE);
7808 /* if the operand is already in dptr
7809 then we do nothing else we move the value to dptr */
7810 if (AOP_TYPE (result) != AOP_STR)
7812 /* if this is remateriazable */
7813 if (AOP_TYPE (result) == AOP_IMMD)
7815 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7816 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7819 { /* we need to get it byte by byte */
7820 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7821 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7822 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7825 /* so dptr know contains the address */
7826 aopOp (right, ic, FALSE);
7828 /* if bit then unpack */
7829 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7830 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7833 size = AOP_SIZE (right);
7838 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7840 emitcode ("lcall", "__gptrput");
7842 emitcode ("inc", "dptr");
7846 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7847 aopPut (AOP(result),"dpl",0);
7848 aopPut (AOP(result),"dph",1);
7851 freeAsmop (result, NULL, ic, TRUE);
7852 freeAsmop (right, NULL, ic, TRUE);
7855 /*-----------------------------------------------------------------*/
7856 /* genPointerSet - stores the value into a pointer location */
7857 /*-----------------------------------------------------------------*/
7859 genPointerSet (iCode * ic, iCode *pi)
7861 operand *right, *result;
7862 sym_link *type, *etype;
7865 right = IC_RIGHT (ic);
7866 result = IC_RESULT (ic);
7868 /* depending on the type of pointer we need to
7869 move it to the correct pointer register */
7870 type = operandType (result);
7871 etype = getSpec (type);
7872 /* if left is of type of pointer then it is simple */
7873 if (IS_PTR (type) && !IS_FUNC (type->next))
7875 p_type = DCL_TYPE (type);
7879 /* we have to go by the storage class */
7880 p_type = PTR_TYPE (SPEC_OCLS (etype));
7883 /* now that we have the pointer type we assign
7884 the pointer values */
7890 genNearPointerSet (right, result, ic, pi);
7894 genPagedPointerSet (right, result, ic, pi);
7898 genFarPointerSet (right, result, ic, pi);
7902 genGenPointerSet (right, result, ic, pi);
7908 /*-----------------------------------------------------------------*/
7909 /* genIfx - generate code for Ifx statement */
7910 /*-----------------------------------------------------------------*/
7912 genIfx (iCode * ic, iCode * popIc)
7914 operand *cond = IC_COND (ic);
7917 aopOp (cond, ic, FALSE);
7919 /* get the value into acc */
7920 if (AOP_TYPE (cond) != AOP_CRY)
7924 /* the result is now in the accumulator */
7925 freeAsmop (cond, NULL, ic, TRUE);
7927 /* if there was something to be popped then do it */
7931 /* if the condition is a bit variable */
7932 if (isbit && IS_ITEMP (cond) &&
7934 genIfxJump (ic, SPIL_LOC (cond)->rname);
7935 else if (isbit && !IS_ITEMP (cond))
7936 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7938 genIfxJump (ic, "a");
7943 /*-----------------------------------------------------------------*/
7944 /* genAddrOf - generates code for address of */
7945 /*-----------------------------------------------------------------*/
7947 genAddrOf (iCode * ic)
7949 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7952 aopOp (IC_RESULT (ic), ic, FALSE);
7954 /* if the operand is on the stack then we
7955 need to get the stack offset of this
7959 /* if it has an offset then we need to compute
7963 emitcode ("mov", "a,_bp");
7964 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7965 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7969 /* we can just move _bp */
7970 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7972 /* fill the result with zero */
7973 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7978 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7984 /* object not on stack then we need the name */
7985 size = AOP_SIZE (IC_RESULT (ic));
7990 char s[SDCC_NAME_MAX];
7992 sprintf (s, "#(%s >> %d)",
7996 sprintf (s, "#%s", sym->rname);
7997 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8001 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8005 /*-----------------------------------------------------------------*/
8006 /* genFarFarAssign - assignment when both are in far space */
8007 /*-----------------------------------------------------------------*/
8009 genFarFarAssign (operand * result, operand * right, iCode * ic)
8011 int size = AOP_SIZE (right);
8014 /* first push the right side on to the stack */
8017 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8019 emitcode ("push", "acc");
8022 freeAsmop (right, NULL, ic, FALSE);
8023 /* now assign DPTR to result */
8024 aopOp (result, ic, FALSE);
8025 size = AOP_SIZE (result);
8028 emitcode ("pop", "acc");
8029 aopPut (AOP (result), "a", --offset);
8031 freeAsmop (result, NULL, ic, FALSE);
8035 /*-----------------------------------------------------------------*/
8036 /* genAssign - generate code for assignment */
8037 /*-----------------------------------------------------------------*/
8039 genAssign (iCode * ic)
8041 operand *result, *right;
8043 unsigned long lit = 0L;
8045 D(emitcode(";","genAssign"));
8047 result = IC_RESULT (ic);
8048 right = IC_RIGHT (ic);
8050 /* if they are the same */
8051 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8054 aopOp (right, ic, FALSE);
8056 /* special case both in far space */
8057 if (AOP_TYPE (right) == AOP_DPTR &&
8058 IS_TRUE_SYMOP (result) &&
8059 isOperandInFarSpace (result))
8062 genFarFarAssign (result, right, ic);
8066 aopOp (result, ic, TRUE);
8068 /* if they are the same registers */
8069 if (sameRegs (AOP (right), AOP (result)))
8072 /* if the result is a bit */
8073 if (AOP_TYPE (result) == AOP_CRY)
8076 /* if the right size is a literal then
8077 we know what the value is */
8078 if (AOP_TYPE (right) == AOP_LIT)
8080 if (((int) operandLitValue (right)))
8081 aopPut (AOP (result), one, 0);
8083 aopPut (AOP (result), zero, 0);
8087 /* the right is also a bit variable */
8088 if (AOP_TYPE (right) == AOP_CRY)
8090 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8091 aopPut (AOP (result), "c", 0);
8097 aopPut (AOP (result), "a", 0);
8101 /* bit variables done */
8103 size = AOP_SIZE (result);
8105 if (AOP_TYPE (right) == AOP_LIT)
8106 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8108 (AOP_TYPE (result) != AOP_REG) &&
8109 (AOP_TYPE (right) == AOP_LIT) &&
8110 !IS_FLOAT (operandType (right)) &&
8113 emitcode ("clr", "a");
8116 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8117 aopPut (AOP (result), "a", size);
8119 aopPut (AOP (result),
8120 aopGet (AOP (right), size, FALSE, FALSE),
8128 aopPut (AOP (result),
8129 aopGet (AOP (right), offset, FALSE, FALSE),
8136 freeAsmop (right, NULL, ic, TRUE);
8137 freeAsmop (result, NULL, ic, TRUE);
8140 /*-----------------------------------------------------------------*/
8141 /* genJumpTab - genrates code for jump table */
8142 /*-----------------------------------------------------------------*/
8144 genJumpTab (iCode * ic)
8149 aopOp (IC_JTCOND (ic), ic, FALSE);
8150 /* get the condition into accumulator */
8151 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8153 /* multiply by three */
8154 emitcode ("add", "a,acc");
8155 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8156 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8158 jtab = newiTempLabel (NULL);
8159 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8160 emitcode ("jmp", "@a+dptr");
8161 emitcode ("", "%05d$:", jtab->key + 100);
8162 /* now generate the jump labels */
8163 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8164 jtab = setNextItem (IC_JTLABELS (ic)))
8165 emitcode ("ljmp", "%05d$", jtab->key + 100);
8169 /*-----------------------------------------------------------------*/
8170 /* genCast - gen code for casting */
8171 /*-----------------------------------------------------------------*/
8173 genCast (iCode * ic)
8175 operand *result = IC_RESULT (ic);
8176 sym_link *ctype = operandType (IC_LEFT (ic));
8177 sym_link *rtype = operandType (IC_RIGHT (ic));
8178 operand *right = IC_RIGHT (ic);
8181 D(emitcode(";", "genCast"));
8183 /* if they are equivalent then do nothing */
8184 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8187 aopOp (right, ic, FALSE);
8188 aopOp (result, ic, FALSE);
8190 /* if the result is a bit */
8191 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8192 if (IS_BITVAR(OP_SYMBOL(result)->type))
8194 /* if the right size is a literal then
8195 we know what the value is */
8196 if (AOP_TYPE (right) == AOP_LIT)
8198 if (((int) operandLitValue (right)))
8199 aopPut (AOP (result), one, 0);
8201 aopPut (AOP (result), zero, 0);
8206 /* the right is also a bit variable */
8207 if (AOP_TYPE (right) == AOP_CRY)
8209 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8210 aopPut (AOP (result), "c", 0);
8216 aopPut (AOP (result), "a", 0);
8220 /* if they are the same size : or less */
8221 if (AOP_SIZE (result) <= AOP_SIZE (right))
8224 /* if they are in the same place */
8225 if (sameRegs (AOP (right), AOP (result)))
8228 /* if they in different places then copy */
8229 size = AOP_SIZE (result);
8233 aopPut (AOP (result),
8234 aopGet (AOP (right), offset, FALSE, FALSE),
8242 /* if the result is of type pointer */
8247 sym_link *type = operandType (right);
8248 sym_link *etype = getSpec (type);
8250 /* pointer to generic pointer */
8251 if (IS_GENPTR (ctype))
8256 p_type = DCL_TYPE (type);
8259 if (SPEC_SCLS(etype)==S_REGISTER) {
8260 // let's assume it is a generic pointer
8263 /* we have to go by the storage class */
8264 p_type = PTR_TYPE (SPEC_OCLS (etype));
8268 /* the first two bytes are known */
8269 size = GPTRSIZE - 1;
8273 aopPut (AOP (result),
8274 aopGet (AOP (right), offset, FALSE, FALSE),
8278 /* the last byte depending on type */
8294 case PPOINTER: // what the fck is this?
8299 /* this should never happen */
8300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8301 "got unknown pointer type");
8304 aopPut (AOP (result), l, GPTRSIZE - 1);
8308 /* just copy the pointers */
8309 size = AOP_SIZE (result);
8313 aopPut (AOP (result),
8314 aopGet (AOP (right), offset, FALSE, FALSE),
8321 /* so we now know that the size of destination is greater
8322 than the size of the source */
8323 /* we move to result for the size of source */
8324 size = AOP_SIZE (right);
8328 aopPut (AOP (result),
8329 aopGet (AOP (right), offset, FALSE, FALSE),
8334 /* now depending on the sign of the source && destination */
8335 size = AOP_SIZE (result) - AOP_SIZE (right);
8336 /* if unsigned or not an integral type */
8337 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8340 aopPut (AOP (result), zero, offset++);
8344 /* we need to extend the sign :{ */
8345 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8348 emitcode ("rlc", "a");
8349 emitcode ("subb", "a,acc");
8351 aopPut (AOP (result), "a", offset++);
8354 /* we are done hurray !!!! */
8357 freeAsmop (right, NULL, ic, TRUE);
8358 freeAsmop (result, NULL, ic, TRUE);
8362 /*-----------------------------------------------------------------*/
8363 /* genDjnz - generate decrement & jump if not zero instrucion */
8364 /*-----------------------------------------------------------------*/
8366 genDjnz (iCode * ic, iCode * ifx)
8372 /* if the if condition has a false label
8373 then we cannot save */
8377 /* if the minus is not of the form
8379 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8380 !IS_OP_LITERAL (IC_RIGHT (ic)))
8383 if (operandLitValue (IC_RIGHT (ic)) != 1)
8386 /* if the size of this greater than one then no
8388 if (getSize (operandType (IC_RESULT (ic))) > 1)
8391 /* otherwise we can save BIG */
8392 lbl = newiTempLabel (NULL);
8393 lbl1 = newiTempLabel (NULL);
8395 aopOp (IC_RESULT (ic), ic, FALSE);
8397 if (AOP_NEEDSACC(IC_RESULT(ic)))
8399 /* If the result is accessed indirectly via
8400 * the accumulator, we must explicitly write
8401 * it back after the decrement.
8403 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8405 if (strcmp(rByte, "a"))
8407 /* Something is hopelessly wrong */
8408 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8409 __FILE__, __LINE__);
8410 /* We can just give up; the generated code will be inefficient,
8413 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8416 emitcode ("dec", "%s", rByte);
8417 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8418 emitcode ("jnz", "%05d$", lbl->key + 100);
8420 else if (IS_AOP_PREG (IC_RESULT (ic)))
8422 emitcode ("dec", "%s",
8423 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8424 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8425 emitcode ("jnz", "%05d$", lbl->key + 100);
8429 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8432 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8433 emitcode ("", "%05d$:", lbl->key + 100);
8434 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8435 emitcode ("", "%05d$:", lbl1->key + 100);
8437 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8442 /*-----------------------------------------------------------------*/
8443 /* genReceive - generate code for a receive iCode */
8444 /*-----------------------------------------------------------------*/
8446 genReceive (iCode * ic)
8448 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8449 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8450 IS_TRUE_SYMOP (IC_RESULT (ic))))
8453 int size = getSize (operandType (IC_RESULT (ic)));
8454 int offset = fReturnSizeMCS51 - size;
8457 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8458 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8461 aopOp (IC_RESULT (ic), ic, FALSE);
8462 size = AOP_SIZE (IC_RESULT (ic));
8466 emitcode ("pop", "acc");
8467 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8474 aopOp (IC_RESULT (ic), ic, FALSE);
8476 assignResultValue (IC_RESULT (ic));
8479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8482 /*-----------------------------------------------------------------*/
8483 /* gen51AggregateAssign - copy complete array's or structures */
8484 /*-----------------------------------------------------------------*/
8485 void gen51AggregateAssign(iCode *ic) {
8486 operand *left=IC_LEFT(ic);
8487 operand *right=IC_RIGHT(ic);
8488 char *fromName=OP_SYMBOL(right)->rname;
8489 char *toName=OP_SYMBOL(left)->rname;
8490 int fromSize=getSize(OP_SYMBOL(right)->type);
8491 int toSize=getSize(OP_SYMBOL(left)->type);
8494 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8495 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8496 // well, this code isn't used yet from anywhere else as for initialising
8497 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8501 if (fromSize!=toSize) {
8502 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8503 ic->filename, ic->lineno);
8508 // use the generic memcpy() for now
8509 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8510 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8511 emitcode ("mov", "a,#%s", fromName);
8512 emitcode ("movx", "@dptr,a");
8513 emitcode ("inc", "dptr");
8514 emitcode ("mov", "a,#(%s>>8)", fromName);
8515 emitcode ("movx", "@dptr,a");
8516 emitcode ("inc", "dptr");
8517 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8518 emitcode ("movx", "@dptr,a");
8519 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8520 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8521 emitcode ("movx", "@dptr,a");
8522 emitcode ("inc", "dptr");
8523 emitcode ("mov", "a,#(%d>>8)", count);
8524 emitcode ("movx", "@dptr,a");
8525 emitcode ("mov", "dptr,#%s", toName);
8526 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8527 emitcode ("lcall", "_memcpy");
8529 // more efficient, but will require the native_memcpy_cs2xs
8530 emitcode ("mov", "r0,#%s", fromName);
8531 emitcode ("mov", "r1,#(%s>>8)", fromName);
8532 emitcode ("mov", "r2,#%s", toName);
8533 emitcode ("mov", "r3,#(%s>>8)", toName);
8534 emitcode ("mov", "r4,#%d", count);
8535 emitcode ("mov", "r5,#(%d>>8)", count);
8536 emitcode ("lcall", "_native_memcpy_cs2xs");
8540 /*-----------------------------------------------------------------*/
8541 /* gen51Code - generate code for 8051 based controllers */
8542 /*-----------------------------------------------------------------*/
8544 gen51Code (iCode * lic)
8549 lineHead = lineCurr = NULL;
8551 /* print the allocation information */
8553 printAllocInfo (currFunc, codeOutFile);
8554 /* if debug information required */
8555 /* if (options.debug && currFunc) { */
8556 if (options.debug && currFunc)
8558 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8560 if (IS_STATIC (currFunc->etype))
8561 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8563 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8566 /* stack pointer name */
8567 if (options.useXstack)
8573 for (ic = lic; ic; ic = ic->next)
8576 if (cln != ic->lineno)
8581 emitcode ("", "C$%s$%d$%d$%d ==.",
8582 FileBaseName (ic->filename), ic->lineno,
8583 ic->level, ic->block);
8586 emitcode (";", "%s %d", ic->filename, ic->lineno);
8589 /* if the result is marked as
8590 spilt and rematerializable or code for
8591 this has already been generated then
8593 if (resultRemat (ic) || ic->generated)
8596 /* depending on the operation */
8616 /* IPOP happens only when trying to restore a
8617 spilt live range, if there is an ifx statement
8618 following this pop then the if statement might
8619 be using some of the registers being popped which
8620 would destory the contents of the register so
8621 we need to check for this condition and handle it */
8623 ic->next->op == IFX &&
8624 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8625 genIfx (ic->next, ic);
8643 genEndFunction (ic);
8663 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8680 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8684 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8691 /* note these two are xlated by algebraic equivalence
8692 during parsing SDCC.y */
8693 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8694 "got '>=' or '<=' shouldn't have come here");
8698 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8710 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8714 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8718 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8745 case GET_VALUE_AT_ADDRESS:
8746 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8750 if (POINTER_SET (ic))
8751 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8777 addSet (&_G.sendSet, ic);
8781 gen51AggregateAssign(ic);
8790 /* now we are ready to call the
8791 peep hole optimizer */
8792 if (!options.nopeep)
8793 peepHole (&lineHead);
8795 /* now do the actual printing */
8796 printLine (lineHead, codeOutFile);