2 /*-------------------------------------------------------------------------
3 SDCCgen51.c - source file for code generation for 8051
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 and - Jean-Louis VERN.jlvern@writeme.com (1999)
7 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
45 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
46 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
47 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
53 #include "SDCCpeeph.h"
57 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
70 {"dpl", "dph", "b", "a"};
71 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
72 char **fReturn = fReturn8051;
73 static char *accUse[] =
76 static short rbank = -1;
90 extern int mcs51_ptrRegReq;
91 extern int mcs51_nRegs;
92 extern FILE *codeOutFile;
93 static void saveRBank (int, iCode *, bool);
94 #define RESULTONSTACK(x) \
95 (IC_RESULT(x) && IC_RESULT(x)->aop && \
96 IC_RESULT(x)->aop->type == AOP_STK )
98 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
99 #define CLRC emitcode("clr","c")
100 #define SETC emitcode("setb","c")
102 static lineNode *lineHead = NULL;
103 static lineNode *lineCurr = NULL;
105 static unsigned char SLMask[] =
106 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
107 0xE0, 0xC0, 0x80, 0x00};
108 static unsigned char SRMask[] =
109 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
121 emitcode (char *inst, char *fmt,...)
124 char lb[INITIAL_INLINEASM];
132 sprintf (lb, "%s\t", inst);
134 sprintf (lb, "%s", inst);
135 vsprintf (lb + (strlen (lb)), fmt, ap);
138 vsprintf (lb, fmt, ap);
140 while (isspace (*lbp))
144 lineCurr = (lineCurr ?
145 connectLine (lineCurr, newLineNode (lb)) :
146 (lineHead = newLineNode (lb)));
147 lineCurr->isInline = _G.inLine;
148 lineCurr->isDebug = _G.debugLine;
152 /*-----------------------------------------------------------------*/
153 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
154 /*-----------------------------------------------------------------*/
156 getFreePtr (iCode * ic, asmop ** aopp, bool result)
158 bool r0iu = FALSE, r1iu = FALSE;
159 bool r0ou = FALSE, r1ou = FALSE;
161 /* the logic: if r0 & r1 used in the instruction
162 then we are in trouble otherwise */
164 /* first check if r0 & r1 are used by this
165 instruction, in which case we are in trouble */
166 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
167 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
172 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
173 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
175 /* if no usage of r0 then return it */
178 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
179 (*aopp)->type = AOP_R0;
181 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
184 /* if no usage of r1 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
188 (*aopp)->type = AOP_R1;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
193 /* now we know they both have usage */
194 /* if r0 not used in this instruction */
197 /* push it if not already pushed */
200 emitcode ("push", "%s",
201 mcs51_regWithIdx (R0_IDX)->dname);
205 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
206 (*aopp)->type = AOP_R0;
208 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
211 /* if r1 not used then */
215 /* push it if not already pushed */
218 emitcode ("push", "%s",
219 mcs51_regWithIdx (R1_IDX)->dname);
223 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
224 (*aopp)->type = AOP_R1;
225 return mcs51_regWithIdx (R1_IDX);
229 /* I said end of world but not quite end of world yet */
230 /* if this is a result then we can push it on the stack */
233 (*aopp)->type = AOP_STK;
237 /* other wise this is true end of the world */
238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
239 "getFreePtr should never reach here");
243 /*-----------------------------------------------------------------*/
244 /* newAsmop - creates a new asmOp */
245 /*-----------------------------------------------------------------*/
247 newAsmop (short type)
251 aop = Safe_calloc (1, sizeof (asmop));
256 /*-----------------------------------------------------------------*/
257 /* pointerCode - returns the code for a pointer type */
258 /*-----------------------------------------------------------------*/
260 pointerCode (sym_link * etype)
263 return PTR_TYPE (SPEC_OCLS (etype));
267 /*-----------------------------------------------------------------*/
268 /* aopForSym - for a true symbol */
269 /*-----------------------------------------------------------------*/
271 aopForSym (iCode * ic, symbol * sym, bool result)
274 memmap *space = SPEC_OCLS (sym->etype);
276 /* if already has one */
280 /* assign depending on the storage class */
281 /* if it is on the stack or indirectly addressable */
282 /* space we need to assign either r0 or r1 to it */
283 if (sym->onStack || sym->iaccess)
285 sym->aop = aop = newAsmop (0);
286 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
287 aop->size = getSize (sym->type);
289 /* now assign the address of the variable to
290 the pointer register */
291 if (aop->type != AOP_STK)
297 emitcode ("push", "acc");
299 emitcode ("mov", "a,_bp");
300 emitcode ("add", "a,#0x%02x",
302 ((char) (sym->stack - _G.nRegsSaved)) :
303 ((char) sym->stack)) & 0xff);
304 emitcode ("mov", "%s,a",
305 aop->aopu.aop_ptr->name);
308 emitcode ("pop", "acc");
311 emitcode ("mov", "%s,#%s",
312 aop->aopu.aop_ptr->name,
314 aop->paged = space->paged;
317 aop->aopu.aop_stk = sym->stack;
321 /* if in bit space */
322 if (IN_BITSPACE (space))
324 sym->aop = aop = newAsmop (AOP_CRY);
325 aop->aopu.aop_dir = sym->rname;
326 aop->size = getSize (sym->type);
329 /* if it is in direct space */
330 if (IN_DIRSPACE (space))
332 sym->aop = aop = newAsmop (AOP_DIR);
333 aop->aopu.aop_dir = sym->rname;
334 aop->size = getSize (sym->type);
338 /* special case for a function */
339 if (IS_FUNC (sym->type))
341 sym->aop = aop = newAsmop (AOP_IMMD);
342 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
343 strcpy (aop->aopu.aop_immd, sym->rname);
344 aop->size = FPTRSIZE;
348 /* only remaining is far space */
349 /* in which case DPTR gets the address */
350 sym->aop = aop = newAsmop (AOP_DPTR);
351 emitcode ("mov", "dptr,#%s", sym->rname);
352 aop->size = getSize (sym->type);
354 /* if it is in code space */
355 if (IN_CODESPACE (space))
361 /*-----------------------------------------------------------------*/
362 /* aopForRemat - rematerialzes an object */
363 /*-----------------------------------------------------------------*/
365 aopForRemat (symbol * sym)
367 iCode *ic = sym->rematiCode;
368 asmop *aop = newAsmop (AOP_IMMD);
374 val += (int) operandLitValue (IC_RIGHT (ic));
375 else if (ic->op == '-')
376 val -= (int) operandLitValue (IC_RIGHT (ic));
380 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
384 sprintf (buffer, "(%s %c 0x%04x)",
385 OP_SYMBOL (IC_LEFT (ic))->rname,
386 val >= 0 ? '+' : '-',
389 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
391 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
392 strcpy (aop->aopu.aop_immd, buffer);
396 /*-----------------------------------------------------------------*/
397 /* regsInCommon - two operands have some registers in common */
398 /*-----------------------------------------------------------------*/
400 regsInCommon (operand * op1, operand * op2)
405 /* if they have registers in common */
406 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
409 sym1 = OP_SYMBOL (op1);
410 sym2 = OP_SYMBOL (op2);
412 if (sym1->nRegs == 0 || sym2->nRegs == 0)
415 for (i = 0; i < sym1->nRegs; i++)
421 for (j = 0; j < sym2->nRegs; j++)
426 if (sym2->regs[j] == sym1->regs[i])
434 /*-----------------------------------------------------------------*/
435 /* operandsEqu - equivalent */
436 /*-----------------------------------------------------------------*/
438 operandsEqu (operand * op1, operand * op2)
442 /* if they not symbols */
443 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
446 sym1 = OP_SYMBOL (op1);
447 sym2 = OP_SYMBOL (op2);
449 /* if both are itemps & one is spilt
450 and the other is not then false */
451 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
452 sym1->isspilt != sym2->isspilt)
455 /* if they are the same */
459 if (strcmp (sym1->rname, sym2->rname) == 0)
463 /* if left is a tmp & right is not */
464 if (IS_ITEMP (op1) &&
467 (sym1->usl.spillLoc == sym2))
470 if (IS_ITEMP (op2) &&
474 (sym2->usl.spillLoc == sym1))
480 /*-----------------------------------------------------------------*/
481 /* sameRegs - two asmops have the same registers */
482 /*-----------------------------------------------------------------*/
484 sameRegs (asmop * aop1, asmop * aop2)
491 if (aop1->type != AOP_REG ||
492 aop2->type != AOP_REG)
495 if (aop1->size != aop2->size)
498 for (i = 0; i < aop1->size; i++)
499 if (aop1->aopu.aop_reg[i] !=
500 aop2->aopu.aop_reg[i])
506 /*-----------------------------------------------------------------*/
507 /* aopOp - allocates an asmop for an operand : */
508 /*-----------------------------------------------------------------*/
510 aopOp (operand * op, iCode * ic, bool result)
519 /* if this a literal */
520 if (IS_OP_LITERAL (op))
522 op->aop = aop = newAsmop (AOP_LIT);
523 aop->aopu.aop_lit = op->operand.valOperand;
524 aop->size = getSize (operandType (op));
528 /* if already has a asmop then continue */
532 /* if the underlying symbol has a aop */
533 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
535 op->aop = OP_SYMBOL (op)->aop;
539 /* if this is a true symbol */
540 if (IS_TRUE_SYMOP (op))
542 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
546 /* this is a temporary : this has
552 e) can be a return use only */
554 sym = OP_SYMBOL (op);
557 /* if the type is a conditional */
558 if (sym->regType == REG_CND)
560 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
565 /* if it is spilt then two situations
567 b) has a spill location */
568 if (sym->isspilt || sym->nRegs == 0)
571 /* rematerialize it NOW */
574 sym->aop = op->aop = aop =
576 aop->size = getSize (sym->type);
583 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
584 aop->size = getSize (sym->type);
585 for (i = 0; i < 2; i++)
586 aop->aopu.aop_str[i] = accUse[i];
593 aop = op->aop = sym->aop = newAsmop (AOP_STR);
594 aop->size = getSize (sym->type);
595 for (i = 0; i < fReturnSizeMCS51; i++)
596 aop->aopu.aop_str[i] = fReturn[i];
600 /* else spill location */
601 sym->aop = op->aop = aop =
602 aopForSym (ic, sym->usl.spillLoc, result);
603 aop->size = getSize (sym->type);
607 /* must be in a register */
608 sym->aop = op->aop = aop = newAsmop (AOP_REG);
609 aop->size = sym->nRegs;
610 for (i = 0; i < sym->nRegs; i++)
611 aop->aopu.aop_reg[i] = sym->regs[i];
614 /*-----------------------------------------------------------------*/
615 /* freeAsmop - free up the asmop given to an operand */
616 /*----------------------------------------------------------------*/
618 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
635 /* depending on the asmop type only three cases need work AOP_RO
636 , AOP_R1 && AOP_STK */
644 emitcode ("pop", "ar0");
648 bitVectUnSetBit (ic->rUsed, R0_IDX);
656 emitcode ("pop", "ar1");
660 bitVectUnSetBit (ic->rUsed, R1_IDX);
666 int stk = aop->aopu.aop_stk + aop->size;
667 bitVectUnSetBit (ic->rUsed, R0_IDX);
668 bitVectUnSetBit (ic->rUsed, R1_IDX);
670 getFreePtr (ic, &aop, FALSE);
674 emitcode ("mov", "a,_bp");
675 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
676 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
680 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
685 emitcode ("pop", "acc");
686 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
689 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
692 freeAsmop (op, NULL, ic, TRUE);
695 emitcode ("pop", "ar0");
701 emitcode ("pop", "ar1");
708 /* all other cases just dealloc */
714 OP_SYMBOL (op)->aop = NULL;
715 /* if the symbol has a spill */
717 SPIL_LOC (op)->aop = NULL;
722 /*-----------------------------------------------------------------*/
723 /* aopGet - for fetching value of the aop */
724 /*-----------------------------------------------------------------*/
726 aopGet (asmop * aop, int offset, bool bit16, bool dname)
731 /* offset is greater than
733 if (offset > (aop->size - 1) &&
734 aop->type != AOP_LIT)
737 /* depending on type */
743 /* if we need to increment it */
744 while (offset > aop->coff)
746 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
750 while (offset < aop->coff)
752 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
759 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
760 return (dname ? "acc" : "a");
762 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
763 rs = Safe_calloc (1, strlen (s) + 1);
768 while (offset > aop->coff)
770 emitcode ("inc", "dptr");
774 while (offset < aop->coff)
776 emitcode ("lcall", "__decdptr");
783 emitcode ("clr", "a");
784 emitcode ("movc", "a,@a+dptr");
788 emitcode ("movx", "a,@dptr");
790 return (dname ? "acc" : "a");
795 sprintf (s, "#%s", aop->aopu.aop_immd);
797 sprintf (s, "#(%s >> %d)",
803 rs = Safe_calloc (1, strlen (s) + 1);
809 sprintf (s, "(%s + %d)",
813 sprintf (s, "%s", aop->aopu.aop_dir);
814 rs = Safe_calloc (1, strlen (s) + 1);
820 return aop->aopu.aop_reg[offset]->dname;
822 return aop->aopu.aop_reg[offset]->name;
825 emitcode ("clr", "a");
826 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
827 emitcode ("rlc", "a");
828 return (dname ? "acc" : "a");
831 if (!offset && dname)
833 return aop->aopu.aop_str[offset];
836 return aopLiteral (aop->aopu.aop_lit, offset);
840 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
844 return aop->aopu.aop_str[offset];
848 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
849 "aopget got unsupported aop->type");
852 /*-----------------------------------------------------------------*/
853 /* aopPut - puts a string for a aop */
854 /*-----------------------------------------------------------------*/
856 aopPut (asmop * aop, char *s, int offset)
860 if (aop->size && offset > (aop->size - 1))
862 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
863 "aopPut got offset > aop->size");
867 /* will assign value to value */
868 /* depending on where it is ofcourse */
873 sprintf (d, "(%s + %d)",
874 aop->aopu.aop_dir, offset);
876 sprintf (d, "%s", aop->aopu.aop_dir);
879 emitcode ("mov", "%s,%s", d, s);
884 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
885 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
888 strcmp (s, "r0") == 0 ||
889 strcmp (s, "r1") == 0 ||
890 strcmp (s, "r2") == 0 ||
891 strcmp (s, "r3") == 0 ||
892 strcmp (s, "r4") == 0 ||
893 strcmp (s, "r5") == 0 ||
894 strcmp (s, "r6") == 0 ||
895 strcmp (s, "r7") == 0)
896 emitcode ("mov", "%s,%s",
897 aop->aopu.aop_reg[offset]->dname, s);
899 emitcode ("mov", "%s,%s",
900 aop->aopu.aop_reg[offset]->name, s);
907 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
908 "aopPut writting to code space");
912 while (offset > aop->coff)
915 emitcode ("inc", "dptr");
918 while (offset < aop->coff)
921 emitcode ("lcall", "__decdptr");
926 /* if not in accumulater */
929 emitcode ("movx", "@dptr,a");
934 while (offset > aop->coff)
937 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
939 while (offset < aop->coff)
942 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
949 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
955 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
957 else if (strcmp (s, "r0") == 0 ||
958 strcmp (s, "r1") == 0 ||
959 strcmp (s, "r2") == 0 ||
960 strcmp (s, "r3") == 0 ||
961 strcmp (s, "r4") == 0 ||
962 strcmp (s, "r5") == 0 ||
963 strcmp (s, "r6") == 0 ||
964 strcmp (s, "r7") == 0)
967 sprintf (buffer, "a%s", s);
968 emitcode ("mov", "@%s,%s",
969 aop->aopu.aop_ptr->name, buffer);
972 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
977 if (strcmp (s, "a") == 0)
978 emitcode ("push", "acc");
980 emitcode ("push", "%s", s);
985 /* if bit variable */
986 if (!aop->aopu.aop_dir)
988 emitcode ("clr", "a");
989 emitcode ("rlc", "a");
994 emitcode ("clr", "%s", aop->aopu.aop_dir);
996 emitcode ("setb", "%s", aop->aopu.aop_dir);
997 else if (!strcmp (s, "c"))
998 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1001 if (strcmp (s, "a"))
1006 symbol *lbl = newiTempLabel (NULL);
1007 emitcode ("clr", "c");
1008 emitcode ("jz", "%05d$", lbl->key + 100);
1009 emitcode ("cpl", "c");
1010 emitcode ("", "%05d$:", lbl->key + 100);
1011 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1019 if (strcmp (aop->aopu.aop_str[offset], s))
1020 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1025 if (!offset && (strcmp (s, "acc") == 0))
1028 if (strcmp (aop->aopu.aop_str[offset], s))
1029 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1033 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1034 "aopPut got unsupported aop->type");
1042 /*-----------------------------------------------------------------*/
1043 /* pointToEnd :- points to the last byte of the operand */
1044 /*-----------------------------------------------------------------*/
1046 pointToEnd (asmop * aop)
1052 aop->coff = count = (aop->size - 1);
1058 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1062 emitcode ("inc", "dptr");
1069 /*-----------------------------------------------------------------*/
1070 /* reAdjustPreg - points a register back to where it should */
1071 /*-----------------------------------------------------------------*/
1073 reAdjustPreg (asmop * aop)
1075 if ((aop->coff==0) || aop->size <= 1)
1083 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1088 emitcode ("lcall", "__decdptr");
1095 #define AOP(op) op->aop
1096 #define AOP_TYPE(op) AOP(op)->type
1097 #define AOP_SIZE(op) AOP(op)->size
1098 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1099 AOP_TYPE(x) == AOP_R0))
1101 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1102 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1104 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1105 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1106 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1108 /*-----------------------------------------------------------------*/
1109 /* genNotFloat - generates not for float operations */
1110 /*-----------------------------------------------------------------*/
1112 genNotFloat (operand * op, operand * res)
1118 /* we will put 127 in the first byte of
1120 aopPut (AOP (res), "#127", 0);
1121 size = AOP_SIZE (op) - 1;
1124 l = aopGet (op->aop, offset++, FALSE, FALSE);
1129 emitcode ("orl", "a,%s",
1131 offset++, FALSE, FALSE));
1134 tlbl = newiTempLabel (NULL);
1135 aopPut (res->aop, one, 1);
1136 emitcode ("jz", "%05d$", (tlbl->key + 100));
1137 aopPut (res->aop, zero, 1);
1138 emitcode ("", "%05d$:", (tlbl->key + 100));
1140 size = res->aop->size - 2;
1142 /* put zeros in the rest */
1144 aopPut (res->aop, zero, offset++);
1147 /*-----------------------------------------------------------------*/
1148 /* opIsGptr: returns non-zero if the passed operand is */
1149 /* a generic pointer type. */
1150 /*-----------------------------------------------------------------*/
1152 opIsGptr (operand * op)
1154 sym_link *type = operandType (op);
1156 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1163 /*-----------------------------------------------------------------*/
1164 /* getDataSize - get the operand data size */
1165 /*-----------------------------------------------------------------*/
1167 getDataSize (operand * op)
1170 size = AOP_SIZE (op);
1171 if (size == GPTRSIZE)
1173 sym_link *type = operandType (op);
1174 if (IS_GENPTR (type))
1176 /* generic pointer; arithmetic operations
1177 * should ignore the high byte (pointer type).
1185 /*-----------------------------------------------------------------*/
1186 /* outAcc - output Acc */
1187 /*-----------------------------------------------------------------*/
1189 outAcc (operand * result)
1192 size = getDataSize (result);
1195 aopPut (AOP (result), "a", 0);
1198 /* unsigned or positive */
1201 aopPut (AOP (result), zero, offset++);
1206 /*-----------------------------------------------------------------*/
1207 /* outBitC - output a bit C */
1208 /*-----------------------------------------------------------------*/
1210 outBitC (operand * result)
1212 /* if the result is bit */
1213 if (AOP_TYPE (result) == AOP_CRY)
1214 aopPut (AOP (result), "c", 0);
1217 emitcode ("clr", "a");
1218 emitcode ("rlc", "a");
1223 /*-----------------------------------------------------------------*/
1224 /* toBoolean - emit code for orl a,operator(sizeop) */
1225 /*-----------------------------------------------------------------*/
1227 toBoolean (operand * oper)
1229 int size = AOP_SIZE (oper) - 1;
1231 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1233 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1237 /*-----------------------------------------------------------------*/
1238 /* genNot - generate code for ! operation */
1239 /*-----------------------------------------------------------------*/
1244 sym_link *optype = operandType (IC_LEFT (ic));
1246 /* assign asmOps to operand & result */
1247 aopOp (IC_LEFT (ic), ic, FALSE);
1248 aopOp (IC_RESULT (ic), ic, TRUE);
1250 /* if in bit space then a special case */
1251 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1253 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1254 emitcode ("cpl", "c");
1255 outBitC (IC_RESULT (ic));
1259 /* if type float then do float */
1260 if (IS_FLOAT (optype))
1262 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1266 toBoolean (IC_LEFT (ic));
1268 tlbl = newiTempLabel (NULL);
1269 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1270 emitcode ("", "%05d$:", tlbl->key + 100);
1271 outBitC (IC_RESULT (ic));
1274 /* release the aops */
1275 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1276 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1280 /*-----------------------------------------------------------------*/
1281 /* genCpl - generate code for complement */
1282 /*-----------------------------------------------------------------*/
1290 /* assign asmOps to operand & result */
1291 aopOp (IC_LEFT (ic), ic, FALSE);
1292 aopOp (IC_RESULT (ic), ic, TRUE);
1294 /* if both are in bit space then
1296 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1297 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1300 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1301 emitcode ("cpl", "c");
1302 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1306 size = AOP_SIZE (IC_RESULT (ic));
1309 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1311 emitcode ("cpl", "a");
1312 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1317 /* release the aops */
1318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1322 /*-----------------------------------------------------------------*/
1323 /* genUminusFloat - unary minus for floating points */
1324 /*-----------------------------------------------------------------*/
1326 genUminusFloat (operand * op, operand * result)
1328 int size, offset = 0;
1330 /* for this we just need to flip the
1331 first it then copy the rest in place */
1332 size = AOP_SIZE (op) - 1;
1333 l = aopGet (AOP (op), 3, FALSE, FALSE);
1337 emitcode ("cpl", "acc.7");
1338 aopPut (AOP (result), "a", 3);
1342 aopPut (AOP (result),
1343 aopGet (AOP (op), offset, FALSE, FALSE),
1349 /*-----------------------------------------------------------------*/
1350 /* genUminus - unary minus code generation */
1351 /*-----------------------------------------------------------------*/
1353 genUminus (iCode * ic)
1356 sym_link *optype, *rtype;
1360 aopOp (IC_LEFT (ic), ic, FALSE);
1361 aopOp (IC_RESULT (ic), ic, TRUE);
1363 /* if both in bit space then special
1365 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1366 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1369 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1370 emitcode ("cpl", "c");
1371 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1375 optype = operandType (IC_LEFT (ic));
1376 rtype = operandType (IC_RESULT (ic));
1378 /* if float then do float stuff */
1379 if (IS_FLOAT (optype))
1381 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1385 /* otherwise subtract from zero */
1386 size = AOP_SIZE (IC_LEFT (ic));
1391 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1392 if (!strcmp (l, "a"))
1396 emitcode ("cpl", "a");
1397 emitcode ("addc", "a,#0");
1403 emitcode ("clr", "a");
1404 emitcode ("subb", "a,%s", l);
1406 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1409 /* if any remaining bytes in the result */
1410 /* we just need to propagate the sign */
1411 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1413 emitcode ("rlc", "a");
1414 emitcode ("subb", "a,acc");
1416 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1420 /* release the aops */
1421 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* saveRegisters - will look for a call and save the registers */
1427 /*-----------------------------------------------------------------*/
1429 saveRegisters (iCode * lic)
1437 for (ic = lic; ic; ic = ic->next)
1438 if (ic->op == CALL || ic->op == PCALL)
1443 fprintf (stderr, "found parameter push with no function call\n");
1447 /* if the registers have been saved already then
1449 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1452 /* find the registers in use at this time
1453 and push them away to safety */
1454 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1458 if (options.useXstack)
1460 if (bitVectBitValue (rsave, R0_IDX))
1461 emitcode ("mov", "b,r0");
1462 emitcode ("mov", "r0,%s", spname);
1463 for (i = 0; i < mcs51_nRegs; i++)
1465 if (bitVectBitValue (rsave, i))
1468 emitcode ("mov", "a,b");
1470 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1471 emitcode ("movx", "@r0,a");
1472 emitcode ("inc", "r0");
1475 emitcode ("mov", "%s,r0", spname);
1476 if (bitVectBitValue (rsave, R0_IDX))
1477 emitcode ("mov", "r0,b");
1480 for (i = 0; i < mcs51_nRegs; i++)
1482 if (bitVectBitValue (rsave, i))
1483 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1486 detype = getSpec (operandType (IC_LEFT (ic)));
1488 #if 0 // why should we do this here??? jwk20011105
1490 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1491 IS_ISR (currFunc->etype) &&
1493 saveRBank (SPEC_BANK (detype), ic, TRUE);
1497 /*-----------------------------------------------------------------*/
1498 /* unsaveRegisters - pop the pushed registers */
1499 /*-----------------------------------------------------------------*/
1501 unsaveRegisters (iCode * ic)
1505 /* find the registers in use at this time
1506 and push them away to safety */
1507 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1510 if (options.useXstack)
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = mcs51_nRegs; i >= 0; i--)
1515 if (bitVectBitValue (rsave, i))
1517 emitcode ("dec", "r0");
1518 emitcode ("movx", "a,@r0");
1520 emitcode ("mov", "b,a");
1522 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1526 emitcode ("mov", "%s,r0", spname);
1527 if (bitVectBitValue (rsave, R0_IDX))
1528 emitcode ("mov", "r0,b");
1531 for (i = mcs51_nRegs; i >= 0; i--)
1533 if (bitVectBitValue (rsave, i))
1534 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1540 /*-----------------------------------------------------------------*/
1542 /*-----------------------------------------------------------------*/
1544 pushSide (operand * oper, int size)
1549 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1550 if (AOP_TYPE (oper) != AOP_REG &&
1551 AOP_TYPE (oper) != AOP_DIR &&
1554 emitcode ("mov", "a,%s", l);
1555 emitcode ("push", "acc");
1558 emitcode ("push", "%s", l);
1562 /*-----------------------------------------------------------------*/
1563 /* assignResultValue - */
1564 /*-----------------------------------------------------------------*/
1566 assignResultValue (operand * oper)
1569 int size = AOP_SIZE (oper);
1572 aopPut (AOP (oper), fReturn[offset], offset);
1578 /*-----------------------------------------------------------------*/
1579 /* genXpush - pushes onto the external stack */
1580 /*-----------------------------------------------------------------*/
1582 genXpush (iCode * ic)
1584 asmop *aop = newAsmop (0);
1586 int size, offset = 0;
1588 aopOp (IC_LEFT (ic), ic, FALSE);
1589 r = getFreePtr (ic, &aop, FALSE);
1592 emitcode ("mov", "%s,_spx", r->name);
1594 size = AOP_SIZE (IC_LEFT (ic));
1598 char *l = aopGet (AOP (IC_LEFT (ic)),
1599 offset++, FALSE, FALSE);
1601 emitcode ("movx", "@%s,a", r->name);
1602 emitcode ("inc", "%s", r->name);
1607 emitcode ("mov", "_spx,%s", r->name);
1609 freeAsmop (NULL, aop, ic, TRUE);
1610 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* genIpush - genrate code for pushing this gets a little complex */
1615 /*-----------------------------------------------------------------*/
1617 genIpush (iCode * ic)
1619 int size, offset = 0;
1623 /* if this is not a parm push : ie. it is spill push
1624 and spill push is always done on the local stack */
1628 /* and the item is spilt then do nothing */
1629 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1632 aopOp (IC_LEFT (ic), ic, FALSE);
1633 size = AOP_SIZE (IC_LEFT (ic));
1634 /* push it on the stack */
1637 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1643 emitcode ("push", "%s", l);
1648 /* this is a paramter push: in this case we call
1649 the routine to find the call and save those
1650 registers that need to be saved */
1653 /* if use external stack then call the external
1654 stack pushing routine */
1655 if (options.useXstack)
1661 /* then do the push */
1662 aopOp (IC_LEFT (ic), ic, FALSE);
1665 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1666 size = AOP_SIZE (IC_LEFT (ic));
1670 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1671 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1672 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1675 emitcode ("mov", "a,%s", l);
1676 emitcode ("push", "acc");
1679 emitcode ("push", "%s", l);
1682 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1685 /*-----------------------------------------------------------------*/
1686 /* genIpop - recover the registers: can happen only for spilling */
1687 /*-----------------------------------------------------------------*/
1689 genIpop (iCode * ic)
1694 /* if the temp was not pushed then */
1695 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1698 aopOp (IC_LEFT (ic), ic, FALSE);
1699 size = AOP_SIZE (IC_LEFT (ic));
1700 offset = (size - 1);
1702 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1705 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1708 /*-----------------------------------------------------------------*/
1709 /* unsaveRBank - restores the resgister bank from stack */
1710 /*-----------------------------------------------------------------*/
1712 unsaveRBank (int bank, iCode * ic, bool popPsw)
1720 if (options.useXstack)
1723 r = getFreePtr (ic, &aop, FALSE);
1726 emitcode ("mov", "%s,_spx", r->name);
1727 emitcode ("movx", "a,@%s", r->name);
1728 emitcode ("mov", "psw,a");
1729 emitcode ("dec", "%s", r->name);
1733 emitcode ("pop", "psw");
1736 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1738 if (options.useXstack)
1740 emitcode ("movx", "a,@%s", r->name);
1741 emitcode ("mov", "(%s+%d),a",
1742 regs8051[i].base, 8 * bank + regs8051[i].offset);
1743 emitcode ("dec", "%s", r->name);
1747 emitcode ("pop", "(%s+%d)",
1748 regs8051[i].base, 8 * bank + regs8051[i].offset);
1751 if (options.useXstack)
1754 emitcode ("mov", "_spx,%s", r->name);
1755 freeAsmop (NULL, aop, ic, TRUE);
1760 /*-----------------------------------------------------------------*/
1761 /* saveRBank - saves an entire register bank on the stack */
1762 /*-----------------------------------------------------------------*/
1764 saveRBank (int bank, iCode * ic, bool pushPsw)
1770 if (options.useXstack)
1774 r = getFreePtr (ic, &aop, FALSE);
1775 emitcode ("mov", "%s,_spx", r->name);
1779 for (i = 0; i < mcs51_nRegs; i++)
1781 if (options.useXstack)
1783 emitcode ("inc", "%s", r->name);
1784 emitcode ("mov", "a,(%s+%d)",
1785 regs8051[i].base, 8 * bank + regs8051[i].offset);
1786 emitcode ("movx", "@%s,a", r->name);
1789 emitcode ("push", "(%s+%d)",
1790 regs8051[i].base, 8 * bank + regs8051[i].offset);
1795 if (options.useXstack)
1797 emitcode ("mov", "a,psw");
1798 emitcode ("movx", "@%s,a", r->name);
1799 emitcode ("inc", "%s", r->name);
1800 emitcode ("mov", "_spx,%s", r->name);
1801 freeAsmop (NULL, aop, ic, TRUE);
1805 emitcode ("push", "psw");
1807 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1813 /*-----------------------------------------------------------------*/
1814 /* genCall - generates a call statement */
1815 /*-----------------------------------------------------------------*/
1817 genCall (iCode * ic)
1821 /* if send set is not empty the assign */
1826 for (sic = setFirstItem (_G.sendSet); sic;
1827 sic = setNextItem (_G.sendSet))
1829 int size, offset = 0;
1830 aopOp (IC_LEFT (sic), sic, FALSE);
1831 size = AOP_SIZE (IC_LEFT (sic));
1834 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1836 if (strcmp (l, fReturn[offset]))
1837 emitcode ("mov", "%s,%s",
1842 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1847 /* if we are calling a function that is not using
1848 the same register bank then we need to save the
1849 destination registers on the stack */
1850 detype = getSpec (operandType (IC_LEFT (ic)));
1852 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1853 IS_ISR (currFunc->etype) &&
1855 saveRBank (SPEC_BANK (detype), ic, TRUE);
1856 } else /* no need to save if we just saved the whole bank */ {
1857 /* if caller saves & we have not saved then */
1863 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1864 OP_SYMBOL (IC_LEFT (ic))->rname :
1865 OP_SYMBOL (IC_LEFT (ic))->name));
1867 /* if we need assign a result value */
1868 if ((IS_ITEMP (IC_RESULT (ic)) &&
1869 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1870 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1871 IS_TRUE_SYMOP (IC_RESULT (ic)))
1875 aopOp (IC_RESULT (ic), ic, FALSE);
1878 assignResultValue (IC_RESULT (ic));
1880 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1883 /* adjust the stack for parameters if
1888 if (ic->parmBytes > 3)
1890 emitcode ("mov", "a,%s", spname);
1891 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1892 emitcode ("mov", "%s,a", spname);
1895 for (i = 0; i < ic->parmBytes; i++)
1896 emitcode ("dec", "%s", spname);
1900 /* if register bank was saved then pop them */
1902 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
1904 /* if we hade saved some registers then unsave them */
1905 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1906 unsaveRegisters (ic);
1911 /*-----------------------------------------------------------------*/
1912 /* genPcall - generates a call by pointer statement */
1913 /*-----------------------------------------------------------------*/
1915 genPcall (iCode * ic)
1918 symbol *rlbl = newiTempLabel (NULL);
1921 /* if caller saves & we have not saved then */
1925 /* if we are calling a function that is not using
1926 the same register bank then we need to save the
1927 destination registers on the stack */
1928 detype = getSpec (operandType (IC_LEFT (ic)));
1930 IS_ISR (currFunc->etype) &&
1931 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1932 saveRBank (SPEC_BANK (detype), ic, TRUE);
1935 /* push the return address on to the stack */
1936 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1937 emitcode ("push", "acc");
1938 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1939 emitcode ("push", "acc");
1941 /* now push the calling address */
1942 aopOp (IC_LEFT (ic), ic, FALSE);
1944 pushSide (IC_LEFT (ic), FPTRSIZE);
1946 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1948 /* if send set is not empty the assign */
1953 for (sic = setFirstItem (_G.sendSet); sic;
1954 sic = setNextItem (_G.sendSet))
1956 int size, offset = 0;
1957 aopOp (IC_LEFT (sic), sic, FALSE);
1958 size = AOP_SIZE (IC_LEFT (sic));
1961 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1963 if (strcmp (l, fReturn[offset]))
1964 emitcode ("mov", "%s,%s",
1969 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1974 emitcode ("ret", "");
1975 emitcode ("", "%05d$:", (rlbl->key + 100));
1978 /* if we need assign a result value */
1979 if ((IS_ITEMP (IC_RESULT (ic)) &&
1980 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1981 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1982 IS_TRUE_SYMOP (IC_RESULT (ic)))
1986 aopOp (IC_RESULT (ic), ic, FALSE);
1989 assignResultValue (IC_RESULT (ic));
1991 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1994 /* adjust the stack for parameters if
1999 if (ic->parmBytes > 3)
2001 emitcode ("mov", "a,%s", spname);
2002 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2003 emitcode ("mov", "%s,a", spname);
2006 for (i = 0; i < ic->parmBytes; i++)
2007 emitcode ("dec", "%s", spname);
2011 /* if register bank was saved then unsave them */
2013 (SPEC_BANK (currFunc->etype) !=
2014 SPEC_BANK (detype)))
2015 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2017 /* if we hade saved some registers then
2020 unsaveRegisters (ic);
2024 /*-----------------------------------------------------------------*/
2025 /* resultRemat - result is rematerializable */
2026 /*-----------------------------------------------------------------*/
2028 resultRemat (iCode * ic)
2030 if (SKIP_IC (ic) || ic->op == IFX)
2033 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2035 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2036 if (sym->remat && !POINTER_SET (ic))
2043 #if defined(__BORLANDC__) || defined(_MSC_VER)
2044 #define STRCASECMP stricmp
2046 #define STRCASECMP strcasecmp
2049 /*-----------------------------------------------------------------*/
2050 /* inExcludeList - return 1 if the string is in exclude Reg list */
2051 /*-----------------------------------------------------------------*/
2053 inExcludeList (char *s)
2057 if (options.excludeRegs[i] &&
2058 STRCASECMP (options.excludeRegs[i], "none") == 0)
2061 for (i = 0; options.excludeRegs[i]; i++)
2063 if (options.excludeRegs[i] &&
2064 STRCASECMP (s, options.excludeRegs[i]) == 0)
2070 /*-----------------------------------------------------------------*/
2071 /* genFunction - generated code for function entry */
2072 /*-----------------------------------------------------------------*/
2074 genFunction (iCode * ic)
2080 /* create the function header */
2081 emitcode (";", "-----------------------------------------");
2082 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2083 emitcode (";", "-----------------------------------------");
2085 emitcode ("", "%s:", sym->rname);
2086 fetype = getSpec (operandType (IC_LEFT (ic)));
2088 /* if critical function then turn interrupts off */
2089 if (SPEC_CRTCL (fetype))
2090 emitcode ("clr", "ea");
2092 /* here we need to generate the equates for the
2093 register bank if required */
2094 if (SPEC_BANK (fetype) != rbank)
2098 rbank = SPEC_BANK (fetype);
2099 for (i = 0; i < mcs51_nRegs; i++)
2101 if (strcmp (regs8051[i].base, "0") == 0)
2102 emitcode ("", "%s = 0x%02x",
2104 8 * rbank + regs8051[i].offset);
2106 emitcode ("", "%s = %s + 0x%02x",
2109 8 * rbank + regs8051[i].offset);
2113 /* if this is an interrupt service routine then
2114 save acc, b, dpl, dph */
2115 if (IS_ISR (sym->etype))
2118 if (!inExcludeList ("acc"))
2119 emitcode ("push", "acc");
2120 if (!inExcludeList ("b"))
2121 emitcode ("push", "b");
2122 if (!inExcludeList ("dpl"))
2123 emitcode ("push", "dpl");
2124 if (!inExcludeList ("dph"))
2125 emitcode ("push", "dph");
2126 /* if this isr has no bank i.e. is going to
2127 run with bank 0 , then we need to save more
2129 if (!SPEC_BANK (sym->etype))
2132 /* if this function does not call any other
2133 function then we can be economical and
2134 save only those registers that are used */
2139 /* if any registers used */
2142 /* save the registers used */
2143 for (i = 0; i < sym->regsUsed->size; i++)
2145 if (bitVectBitValue (sym->regsUsed, i) ||
2146 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2147 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2154 /* this function has a function call cannot
2155 determines register usage so we will have to push the
2157 saveRBank (0, ic, FALSE);
2163 /* if callee-save to be used for this function
2164 then save the registers being used in this function */
2165 if (sym->calleeSave)
2169 /* if any registers used */
2172 /* save the registers used */
2173 for (i = 0; i < sym->regsUsed->size; i++)
2175 if (bitVectBitValue (sym->regsUsed, i) ||
2176 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2178 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2186 /* set the register bank to the desired value */
2187 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2189 emitcode ("push", "psw");
2190 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2193 if (IS_RENT (sym->etype) || options.stackAuto)
2196 if (options.useXstack)
2198 emitcode ("mov", "r0,%s", spname);
2199 emitcode ("mov", "a,_bp");
2200 emitcode ("movx", "@r0,a");
2201 emitcode ("inc", "%s", spname);
2205 /* set up the stack */
2206 emitcode ("push", "_bp"); /* save the callers stack */
2208 emitcode ("mov", "_bp,%s", spname);
2211 /* adjust the stack for the function */
2217 werror (W_STACK_OVERFLOW, sym->name);
2219 if (i > 3 && sym->recvSize < 4)
2222 emitcode ("mov", "a,sp");
2223 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2224 emitcode ("mov", "sp,a");
2229 emitcode ("inc", "sp");
2235 emitcode ("mov", "a,_spx");
2236 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2237 emitcode ("mov", "_spx,a");
2242 /*-----------------------------------------------------------------*/
2243 /* genEndFunction - generates epilogue for functions */
2244 /*-----------------------------------------------------------------*/
2246 genEndFunction (iCode * ic)
2248 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2250 if (IS_RENT (sym->etype) || options.stackAuto)
2252 emitcode ("mov", "%s,_bp", spname);
2255 /* if use external stack but some variables were
2256 added to the local stack then decrement the
2258 if (options.useXstack && sym->stack)
2260 emitcode ("mov", "a,sp");
2261 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2262 emitcode ("mov", "sp,a");
2266 if ((IS_RENT (sym->etype) || options.stackAuto))
2268 if (options.useXstack)
2270 emitcode ("mov", "r0,%s", spname);
2271 emitcode ("movx", "a,@r0");
2272 emitcode ("mov", "_bp,a");
2273 emitcode ("dec", "%s", spname);
2277 emitcode ("pop", "_bp");
2281 /* restore the register bank */
2282 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2283 emitcode ("pop", "psw");
2285 if (IS_ISR (sym->etype))
2288 /* now we need to restore the registers */
2289 /* if this isr has no bank i.e. is going to
2290 run with bank 0 , then we need to save more
2292 if (!SPEC_BANK (sym->etype))
2295 /* if this function does not call any other
2296 function then we can be economical and
2297 save only those registers that are used */
2302 /* if any registers used */
2305 /* save the registers used */
2306 for (i = sym->regsUsed->size; i >= 0; i--)
2308 if (bitVectBitValue (sym->regsUsed, i) ||
2309 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2310 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2317 /* this function has a function call cannot
2318 determines register usage so we will have to pop the
2320 unsaveRBank (0, ic, FALSE);
2324 if (!inExcludeList ("dph"))
2325 emitcode ("pop", "dph");
2326 if (!inExcludeList ("dpl"))
2327 emitcode ("pop", "dpl");
2328 if (!inExcludeList ("b"))
2329 emitcode ("pop", "b");
2330 if (!inExcludeList ("acc"))
2331 emitcode ("pop", "acc");
2333 if (SPEC_CRTCL (sym->etype))
2334 emitcode ("setb", "ea");
2336 /* if debug then send end of function */
2337 /* if (options.debug && currFunc) { */
2341 emitcode ("", "C$%s$%d$%d$%d ==.",
2342 FileBaseName (ic->filename), currFunc->lastLine,
2343 ic->level, ic->block);
2344 if (IS_STATIC (currFunc->etype))
2345 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2347 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2351 emitcode ("reti", "");
2355 if (SPEC_CRTCL (sym->etype))
2356 emitcode ("setb", "ea");
2358 if (sym->calleeSave)
2362 /* if any registers used */
2365 /* save the registers used */
2366 for (i = sym->regsUsed->size; i >= 0; i--)
2368 if (bitVectBitValue (sym->regsUsed, i) ||
2369 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2370 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2376 /* if debug then send end of function */
2380 emitcode ("", "C$%s$%d$%d$%d ==.",
2381 FileBaseName (ic->filename), currFunc->lastLine,
2382 ic->level, ic->block);
2383 if (IS_STATIC (currFunc->etype))
2384 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2386 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2390 emitcode ("ret", "");
2395 /*-----------------------------------------------------------------*/
2396 /* genRet - generate code for return statement */
2397 /*-----------------------------------------------------------------*/
2401 int size, offset = 0, pushed = 0;
2403 /* if we have no return value then
2404 just generate the "ret" */
2408 /* we have something to return then
2409 move the return value into place */
2410 aopOp (IC_LEFT (ic), ic, FALSE);
2411 size = AOP_SIZE (IC_LEFT (ic));
2416 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2419 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2421 emitcode ("push", "%s", l);
2426 l = aopGet (AOP (IC_LEFT (ic)), offset,
2428 if (strcmp (fReturn[offset], l))
2429 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2438 if (strcmp (fReturn[pushed], "a"))
2439 emitcode ("pop", fReturn[pushed]);
2441 emitcode ("pop", "acc");
2444 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2447 /* generate a jump to the return label
2448 if the next is not the return statement */
2449 if (!(ic->next && ic->next->op == LABEL &&
2450 IC_LABEL (ic->next) == returnLabel))
2452 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2456 /*-----------------------------------------------------------------*/
2457 /* genLabel - generates a label */
2458 /*-----------------------------------------------------------------*/
2460 genLabel (iCode * ic)
2462 /* special case never generate */
2463 if (IC_LABEL (ic) == entryLabel)
2466 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2469 /*-----------------------------------------------------------------*/
2470 /* genGoto - generates a ljmp */
2471 /*-----------------------------------------------------------------*/
2473 genGoto (iCode * ic)
2475 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2478 /*-----------------------------------------------------------------*/
2479 /* findLabelBackwards: walks back through the iCode chain looking */
2480 /* for the given label. Returns number of iCode instructions */
2481 /* between that label and given ic. */
2482 /* Returns zero if label not found. */
2483 /*-----------------------------------------------------------------*/
2485 findLabelBackwards (iCode * ic, int key)
2494 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2496 /* printf("findLabelBackwards = %d\n", count); */
2504 /*-----------------------------------------------------------------*/
2505 /* genPlusIncr :- does addition with increment if possible */
2506 /*-----------------------------------------------------------------*/
2508 genPlusIncr (iCode * ic)
2510 unsigned int icount;
2511 unsigned int size = getDataSize (IC_RESULT (ic));
2513 /* will try to generate an increment */
2514 /* if the right side is not a literal
2516 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2519 /* if the literal value of the right hand side
2520 is greater than 4 then it is not worth it */
2521 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2524 /* if increment 16 bits in register */
2525 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2533 /* If the next instruction is a goto and the goto target
2534 * is < 10 instructions previous to this, we can generate
2535 * jumps straight to that target.
2537 if (ic->next && ic->next->op == GOTO
2538 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2539 && labelRange <= 10)
2541 emitcode (";", "tail increment optimized");
2542 tlbl = IC_LABEL (ic->next);
2547 tlbl = newiTempLabel (NULL);
2550 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2551 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2552 IS_AOP_PREG (IC_RESULT (ic)))
2553 emitcode ("cjne", "%s,#0x00,%05d$"
2554 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2558 emitcode ("clr", "a");
2559 emitcode ("cjne", "a,%s,%05d$"
2560 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2564 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2567 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2568 IS_AOP_PREG (IC_RESULT (ic)))
2569 emitcode ("cjne", "%s,#0x00,%05d$"
2570 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2573 emitcode ("cjne", "a,%s,%05d$"
2574 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2577 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2581 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2582 IS_AOP_PREG (IC_RESULT (ic)))
2583 emitcode ("cjne", "%s,#0x00,%05d$"
2584 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2588 emitcode ("cjne", "a,%s,%05d$"
2589 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2592 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2597 emitcode ("", "%05d$:", tlbl->key + 100);
2602 /* if the sizes are greater than 1 then we cannot */
2603 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2604 AOP_SIZE (IC_LEFT (ic)) > 1)
2607 /* we can if the aops of the left & result match or
2608 if they are in registers and the registers are the
2610 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2615 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2616 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2617 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2623 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2632 /*-----------------------------------------------------------------*/
2633 /* outBitAcc - output a bit in acc */
2634 /*-----------------------------------------------------------------*/
2636 outBitAcc (operand * result)
2638 symbol *tlbl = newiTempLabel (NULL);
2639 /* if the result is a bit */
2640 if (AOP_TYPE (result) == AOP_CRY)
2642 aopPut (AOP (result), "a", 0);
2646 emitcode ("jz", "%05d$", tlbl->key + 100);
2647 emitcode ("mov", "a,%s", one);
2648 emitcode ("", "%05d$:", tlbl->key + 100);
2653 /*-----------------------------------------------------------------*/
2654 /* genPlusBits - generates code for addition of two bits */
2655 /*-----------------------------------------------------------------*/
2657 genPlusBits (iCode * ic)
2659 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2661 symbol *lbl = newiTempLabel (NULL);
2662 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2663 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2664 emitcode ("cpl", "c");
2665 emitcode ("", "%05d$:", (lbl->key + 100));
2666 outBitC (IC_RESULT (ic));
2670 emitcode ("clr", "a");
2671 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2672 emitcode ("rlc", "a");
2673 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2674 emitcode ("addc", "a,#0x00");
2675 outAcc (IC_RESULT (ic));
2680 /* This is the original version of this code.
2682 * This is being kept around for reference,
2683 * because I am not entirely sure I got it right...
2686 adjustArithmeticResult (iCode * ic)
2688 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2689 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2690 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2691 aopPut (AOP (IC_RESULT (ic)),
2692 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2695 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2696 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2697 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2698 aopPut (AOP (IC_RESULT (ic)),
2699 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2702 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2703 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2704 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2705 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2706 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2709 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2710 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2714 /* This is the pure and virtuous version of this code.
2715 * I'm pretty certain it's right, but not enough to toss the old
2719 adjustArithmeticResult (iCode * ic)
2721 if (opIsGptr (IC_RESULT (ic)) &&
2722 opIsGptr (IC_LEFT (ic)) &&
2723 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2725 aopPut (AOP (IC_RESULT (ic)),
2726 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2730 if (opIsGptr (IC_RESULT (ic)) &&
2731 opIsGptr (IC_RIGHT (ic)) &&
2732 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2734 aopPut (AOP (IC_RESULT (ic)),
2735 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2739 if (opIsGptr (IC_RESULT (ic)) &&
2740 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2741 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2742 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2743 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2746 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2747 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2752 /*-----------------------------------------------------------------*/
2753 /* genPlus - generates code for addition */
2754 /*-----------------------------------------------------------------*/
2756 genPlus (iCode * ic)
2758 int size, offset = 0;
2760 /* special cases :- */
2762 aopOp (IC_LEFT (ic), ic, FALSE);
2763 aopOp (IC_RIGHT (ic), ic, FALSE);
2764 aopOp (IC_RESULT (ic), ic, TRUE);
2766 /* if literal, literal on the right or
2767 if left requires ACC or right is already
2769 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2770 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2771 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2773 operand *t = IC_RIGHT (ic);
2774 IC_RIGHT (ic) = IC_LEFT (ic);
2778 /* if both left & right are in bit
2780 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2781 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2787 /* if left in bit space & right literal */
2788 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2789 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2791 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2792 /* if result in bit space */
2793 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2795 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2796 emitcode ("cpl", "c");
2797 outBitC (IC_RESULT (ic));
2801 size = getDataSize (IC_RESULT (ic));
2804 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2805 emitcode ("addc", "a,#00");
2806 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2812 /* if I can do an increment instead
2813 of add then GOOD for ME */
2814 if (genPlusIncr (ic) == TRUE)
2817 size = getDataSize (IC_RESULT (ic));
2821 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2823 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2825 emitcode ("add", "a,%s",
2826 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2828 emitcode ("addc", "a,%s",
2829 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2833 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2835 emitcode ("add", "a,%s",
2836 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2838 emitcode ("addc", "a,%s",
2839 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2841 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2844 adjustArithmeticResult (ic);
2847 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2848 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2849 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2852 /*-----------------------------------------------------------------*/
2853 /* genMinusDec :- does subtraction with deccrement if possible */
2854 /*-----------------------------------------------------------------*/
2856 genMinusDec (iCode * ic)
2858 unsigned int icount;
2859 unsigned int size = getDataSize (IC_RESULT (ic));
2861 /* will try to generate an increment */
2862 /* if the right side is not a literal
2864 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2867 /* if the literal value of the right hand side
2868 is greater than 4 then it is not worth it */
2869 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2872 /* if decrement 16 bits in register */
2873 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2881 /* If the next instruction is a goto and the goto target
2882 * is <= 10 instructions previous to this, we can generate
2883 * jumps straight to that target.
2885 if (ic->next && ic->next->op == GOTO
2886 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2887 && labelRange <= 10)
2889 emitcode (";", "tail decrement optimized");
2890 tlbl = IC_LABEL (ic->next);
2895 tlbl = newiTempLabel (NULL);
2899 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2900 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2901 IS_AOP_PREG (IC_RESULT (ic)))
2902 emitcode ("cjne", "%s,#0xff,%05d$"
2903 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2907 emitcode ("mov", "a,#0xff");
2908 emitcode ("cjne", "a,%s,%05d$"
2909 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2912 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2915 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2916 IS_AOP_PREG (IC_RESULT (ic)))
2917 emitcode ("cjne", "%s,#0xff,%05d$"
2918 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2922 emitcode ("cjne", "a,%s,%05d$"
2923 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2926 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2931 IS_AOP_PREG (IC_RESULT (ic)))
2932 emitcode ("cjne", "%s,#0xff,%05d$"
2933 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2937 emitcode ("cjne", "a,%s,%05d$"
2938 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2941 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2945 emitcode ("", "%05d$:", tlbl->key + 100);
2950 /* if the sizes are greater than 1 then we cannot */
2951 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2952 AOP_SIZE (IC_LEFT (ic)) > 1)
2955 /* we can if the aops of the left & result match or
2956 if they are in registers and the registers are the
2958 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2962 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
2970 /*-----------------------------------------------------------------*/
2971 /* addSign - complete with sign */
2972 /*-----------------------------------------------------------------*/
2974 addSign (operand * result, int offset, int sign)
2976 int size = (getDataSize (result) - offset);
2981 emitcode ("rlc", "a");
2982 emitcode ("subb", "a,acc");
2984 aopPut (AOP (result), "a", offset++);
2988 aopPut (AOP (result), zero, offset++);
2992 /*-----------------------------------------------------------------*/
2993 /* genMinusBits - generates code for subtraction of two bits */
2994 /*-----------------------------------------------------------------*/
2996 genMinusBits (iCode * ic)
2998 symbol *lbl = newiTempLabel (NULL);
2999 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3001 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3002 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3003 emitcode ("cpl", "c");
3004 emitcode ("", "%05d$:", (lbl->key + 100));
3005 outBitC (IC_RESULT (ic));
3009 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3010 emitcode ("subb", "a,acc");
3011 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3012 emitcode ("inc", "a");
3013 emitcode ("", "%05d$:", (lbl->key + 100));
3014 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3015 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3019 /*-----------------------------------------------------------------*/
3020 /* genMinus - generates code for subtraction */
3021 /*-----------------------------------------------------------------*/
3023 genMinus (iCode * ic)
3025 int size, offset = 0;
3026 unsigned long lit = 0L;
3028 aopOp (IC_LEFT (ic), ic, FALSE);
3029 aopOp (IC_RIGHT (ic), ic, FALSE);
3030 aopOp (IC_RESULT (ic), ic, TRUE);
3032 /* special cases :- */
3033 /* if both left & right are in bit space */
3034 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3035 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3041 /* if I can do an decrement instead
3042 of subtract then GOOD for ME */
3043 if (genMinusDec (ic) == TRUE)
3046 size = getDataSize (IC_RESULT (ic));
3048 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3054 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3058 /* if literal, add a,#-lit, else normal subb */
3061 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3062 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3063 emitcode ("subb", "a,%s",
3064 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3067 /* first add without previous c */
3069 emitcode ("add", "a,#0x%02x",
3070 (unsigned int) (lit & 0x0FFL));
3072 emitcode ("addc", "a,#0x%02x",
3073 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3075 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3078 adjustArithmeticResult (ic);
3081 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3082 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3083 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3087 /*-----------------------------------------------------------------*/
3088 /* genMultbits :- multiplication of bits */
3089 /*-----------------------------------------------------------------*/
3091 genMultbits (operand * left,
3095 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3096 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3101 /*-----------------------------------------------------------------*/
3102 /* genMultOneByte : 8*8=8/16 bit multiplication */
3103 /*-----------------------------------------------------------------*/
3105 genMultOneByte (operand * left,
3109 sym_link *opetype = operandType (result);
3111 int size=AOP_SIZE(result);
3113 //emitcode (";",__FUNCTION__);
3114 if (size<1 || size>2) {
3115 // this should never happen
3116 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3117 AOP_SIZE(result), __FILE__, lineno);
3121 /* (if two literals: the value is computed before) */
3122 /* if one literal, literal on the right */
3123 if (AOP_TYPE (left) == AOP_LIT)
3128 //emitcode (";", "swapped left and right");
3131 if (SPEC_USIGN(opetype)
3132 // ignore the sign of left and right, what else can we do?
3133 || (SPEC_USIGN(operandType(left)) &&
3134 SPEC_USIGN(operandType(right)))) {
3135 // just an unsigned 8*8=8/16 multiply
3136 //emitcode (";","unsigned");
3137 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3138 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3139 emitcode ("mul", "ab");
3140 aopPut (AOP (result), "a", 0);
3142 aopPut (AOP (result), "b", 1);
3147 // we have to do a signed multiply
3149 //emitcode (";", "signed");
3150 emitcode ("clr", "F0"); // reset sign flag
3151 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3152 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3154 lbl=newiTempLabel(NULL);
3155 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3156 // left side is negative, 8-bit two's complement, this fails for -128
3157 emitcode ("setb", "F0"); // set sign flag
3158 emitcode ("cpl", "a");
3159 emitcode ("inc", "a");
3161 emitcode ("", "%05d$:", lbl->key+100);
3162 emitcode ("xch", "a,b");
3165 if (AOP_TYPE(right)==AOP_LIT) {
3166 /* AND literal negative */
3167 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3168 // two's complement for literal<0
3169 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3170 emitcode ("cpl", "a");
3171 emitcode ("inc", "a");
3174 lbl=newiTempLabel(NULL);
3175 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3176 // right side is negative, 8-bit two's complement
3177 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3178 emitcode ("cpl", "a");
3179 emitcode ("inc", "a");
3180 emitcode ("", "%05d$:", lbl->key+100);
3182 emitcode ("mul", "ab");
3184 lbl=newiTempLabel(NULL);
3185 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3186 // only ONE op was negative, we have to do a 8/16-bit two's complement
3187 emitcode ("cpl", "a"); // lsb
3189 emitcode ("inc", "a");
3191 emitcode ("add", "a,#1");
3192 emitcode ("xch", "a,b");
3193 emitcode ("cpl", "a"); // msb
3194 emitcode ("addc", "a,#0");
3195 emitcode ("xch", "a,b");
3198 emitcode ("", "%05d$:", lbl->key+100);
3199 aopPut (AOP (result), "a", 0);
3201 aopPut (AOP (result), "b", 1);
3205 /*-----------------------------------------------------------------*/
3206 /* genMult - generates code for multiplication */
3207 /*-----------------------------------------------------------------*/
3209 genMult (iCode * ic)
3211 operand *left = IC_LEFT (ic);
3212 operand *right = IC_RIGHT (ic);
3213 operand *result = IC_RESULT (ic);
3215 /* assign the amsops */
3216 aopOp (left, ic, FALSE);
3217 aopOp (right, ic, FALSE);
3218 aopOp (result, ic, TRUE);
3220 /* special cases first */
3222 if (AOP_TYPE (left) == AOP_CRY &&
3223 AOP_TYPE (right) == AOP_CRY)
3225 genMultbits (left, right, result);
3229 /* if both are of size == 1 */
3230 if (AOP_SIZE (left) == 1 &&
3231 AOP_SIZE (right) == 1)
3233 genMultOneByte (left, right, result);
3237 /* should have been converted to function call */
3241 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3242 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3243 freeAsmop (result, NULL, ic, TRUE);
3246 /*-----------------------------------------------------------------*/
3247 /* genDivbits :- division of bits */
3248 /*-----------------------------------------------------------------*/
3250 genDivbits (operand * left,
3257 /* the result must be bit */
3258 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3259 l = aopGet (AOP (left), 0, FALSE, FALSE);
3263 emitcode ("div", "ab");
3264 emitcode ("rrc", "a");
3265 aopPut (AOP (result), "c", 0);
3268 /*-----------------------------------------------------------------*/
3269 /* genDivOneByte : 8 bit division */
3270 /*-----------------------------------------------------------------*/
3272 genDivOneByte (operand * left,
3276 sym_link *opetype = operandType (result);
3281 size = AOP_SIZE (result) - 1;
3283 /* signed or unsigned */
3284 if (SPEC_USIGN (opetype))
3286 /* unsigned is easy */
3287 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3288 l = aopGet (AOP (left), 0, FALSE, FALSE);
3290 emitcode ("div", "ab");
3291 aopPut (AOP (result), "a", 0);
3293 aopPut (AOP (result), zero, offset++);
3297 /* signed is a little bit more difficult */
3299 /* save the signs of the operands */
3300 l = aopGet (AOP (left), 0, FALSE, FALSE);
3302 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3303 emitcode ("push", "acc"); /* save it on the stack */
3305 /* now sign adjust for both left & right */
3306 l = aopGet (AOP (right), 0, FALSE, FALSE);
3308 lbl = newiTempLabel (NULL);
3309 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3310 emitcode ("cpl", "a");
3311 emitcode ("inc", "a");
3312 emitcode ("", "%05d$:", (lbl->key + 100));
3313 emitcode ("mov", "b,a");
3315 /* sign adjust left side */
3316 l = aopGet (AOP (left), 0, FALSE, FALSE);
3319 lbl = newiTempLabel (NULL);
3320 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3321 emitcode ("cpl", "a");
3322 emitcode ("inc", "a");
3323 emitcode ("", "%05d$:", (lbl->key + 100));
3325 /* now the division */
3326 emitcode ("div", "ab");
3327 /* we are interested in the lower order
3329 emitcode ("mov", "b,a");
3330 lbl = newiTempLabel (NULL);
3331 emitcode ("pop", "acc");
3332 /* if there was an over flow we don't
3333 adjust the sign of the result */
3334 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3335 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3337 emitcode ("clr", "a");
3338 emitcode ("subb", "a,b");
3339 emitcode ("mov", "b,a");
3340 emitcode ("", "%05d$:", (lbl->key + 100));
3342 /* now we are done */
3343 aopPut (AOP (result), "b", 0);
3346 emitcode ("mov", "c,b.7");
3347 emitcode ("subb", "a,acc");
3350 aopPut (AOP (result), "a", offset++);
3354 /*-----------------------------------------------------------------*/
3355 /* genDiv - generates code for division */
3356 /*-----------------------------------------------------------------*/
3360 operand *left = IC_LEFT (ic);
3361 operand *right = IC_RIGHT (ic);
3362 operand *result = IC_RESULT (ic);
3364 /* assign the amsops */
3365 aopOp (left, ic, FALSE);
3366 aopOp (right, ic, FALSE);
3367 aopOp (result, ic, TRUE);
3369 /* special cases first */
3371 if (AOP_TYPE (left) == AOP_CRY &&
3372 AOP_TYPE (right) == AOP_CRY)
3374 genDivbits (left, right, result);
3378 /* if both are of size == 1 */
3379 if (AOP_SIZE (left) == 1 &&
3380 AOP_SIZE (right) == 1)
3382 genDivOneByte (left, right, result);
3386 /* should have been converted to function call */
3389 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3390 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3391 freeAsmop (result, NULL, ic, TRUE);
3394 /*-----------------------------------------------------------------*/
3395 /* genModbits :- modulus of bits */
3396 /*-----------------------------------------------------------------*/
3398 genModbits (operand * left,
3405 /* the result must be bit */
3406 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3407 l = aopGet (AOP (left), 0, FALSE, FALSE);
3411 emitcode ("div", "ab");
3412 emitcode ("mov", "a,b");
3413 emitcode ("rrc", "a");
3414 aopPut (AOP (result), "c", 0);
3417 /*-----------------------------------------------------------------*/
3418 /* genModOneByte : 8 bit modulus */
3419 /*-----------------------------------------------------------------*/
3421 genModOneByte (operand * left,
3425 sym_link *opetype = operandType (result);
3429 /* signed or unsigned */
3430 if (SPEC_USIGN (opetype))
3432 /* unsigned is easy */
3433 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3434 l = aopGet (AOP (left), 0, FALSE, FALSE);
3436 emitcode ("div", "ab");
3437 aopPut (AOP (result), "b", 0);
3441 /* signed is a little bit more difficult */
3443 /* save the signs of the operands */
3444 l = aopGet (AOP (left), 0, FALSE, FALSE);
3447 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3448 emitcode ("push", "acc"); /* save it on the stack */
3450 /* now sign adjust for both left & right */
3451 l = aopGet (AOP (right), 0, FALSE, FALSE);
3454 lbl = newiTempLabel (NULL);
3455 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3456 emitcode ("cpl", "a");
3457 emitcode ("inc", "a");
3458 emitcode ("", "%05d$:", (lbl->key + 100));
3459 emitcode ("mov", "b,a");
3461 /* sign adjust left side */
3462 l = aopGet (AOP (left), 0, FALSE, FALSE);
3465 lbl = newiTempLabel (NULL);
3466 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3467 emitcode ("cpl", "a");
3468 emitcode ("inc", "a");
3469 emitcode ("", "%05d$:", (lbl->key + 100));
3471 /* now the multiplication */
3472 emitcode ("div", "ab");
3473 /* we are interested in the lower order
3475 lbl = newiTempLabel (NULL);
3476 emitcode ("pop", "acc");
3477 /* if there was an over flow we don't
3478 adjust the sign of the result */
3479 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3480 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3482 emitcode ("clr", "a");
3483 emitcode ("subb", "a,b");
3484 emitcode ("mov", "b,a");
3485 emitcode ("", "%05d$:", (lbl->key + 100));
3487 /* now we are done */
3488 aopPut (AOP (result), "b", 0);
3492 /*-----------------------------------------------------------------*/
3493 /* genMod - generates code for division */
3494 /*-----------------------------------------------------------------*/
3498 operand *left = IC_LEFT (ic);
3499 operand *right = IC_RIGHT (ic);
3500 operand *result = IC_RESULT (ic);
3502 /* assign the amsops */
3503 aopOp (left, ic, FALSE);
3504 aopOp (right, ic, FALSE);
3505 aopOp (result, ic, TRUE);
3507 /* special cases first */
3509 if (AOP_TYPE (left) == AOP_CRY &&
3510 AOP_TYPE (right) == AOP_CRY)
3512 genModbits (left, right, result);
3516 /* if both are of size == 1 */
3517 if (AOP_SIZE (left) == 1 &&
3518 AOP_SIZE (right) == 1)
3520 genModOneByte (left, right, result);
3524 /* should have been converted to function call */
3528 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3530 freeAsmop (result, NULL, ic, TRUE);
3533 /*-----------------------------------------------------------------*/
3534 /* genIfxJump :- will create a jump depending on the ifx */
3535 /*-----------------------------------------------------------------*/
3537 genIfxJump (iCode * ic, char *jval)
3540 symbol *tlbl = newiTempLabel (NULL);
3543 /* if true label then we jump if condition
3547 jlbl = IC_TRUE (ic);
3548 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3549 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3553 /* false label is present */
3554 jlbl = IC_FALSE (ic);
3555 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3556 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3558 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3559 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3561 emitcode (inst, "%05d$", tlbl->key + 100);
3562 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3563 emitcode ("", "%05d$:", tlbl->key + 100);
3565 /* mark the icode as generated */
3569 /*-----------------------------------------------------------------*/
3570 /* genCmp :- greater or less than comparison */
3571 /*-----------------------------------------------------------------*/
3573 genCmp (operand * left, operand * right,
3574 operand * result, iCode * ifx, int sign, iCode *ic)
3576 int size, offset = 0;
3577 unsigned long lit = 0L;
3579 /* if left & right are bit variables */
3580 if (AOP_TYPE (left) == AOP_CRY &&
3581 AOP_TYPE (right) == AOP_CRY)
3583 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3584 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3588 /* subtract right from left if at the
3589 end the carry flag is set then we know that
3590 left is greater than right */
3591 size = max (AOP_SIZE (left), AOP_SIZE (right));
3593 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3594 if ((size == 1) && !sign &&
3595 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3597 symbol *lbl = newiTempLabel (NULL);
3598 emitcode ("cjne", "%s,%s,%05d$",
3599 aopGet (AOP (left), offset, FALSE, FALSE),
3600 aopGet (AOP (right), offset, FALSE, FALSE),
3602 emitcode ("", "%05d$:", lbl->key + 100);
3606 if (AOP_TYPE (right) == AOP_LIT)
3608 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3609 /* optimize if(x < 0) or if(x >= 0) */
3618 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3619 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3621 genIfxJump (ifx, "acc.7");
3625 emitcode ("rlc", "a");
3633 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3634 if (sign && size == 0)
3636 emitcode ("xrl", "a,#0x80");
3637 if (AOP_TYPE (right) == AOP_LIT)
3639 unsigned long lit = (unsigned long)
3640 floatFromVal (AOP (right)->aopu.aop_lit);
3641 emitcode ("subb", "a,#0x%02x",
3642 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3646 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3647 emitcode ("xrl", "b,#0x80");
3648 emitcode ("subb", "a,b");
3652 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3658 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3659 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3660 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3666 /* if the result is used in the next
3667 ifx conditional branch then generate
3668 code a little differently */
3670 genIfxJump (ifx, "c");
3673 /* leave the result in acc */
3677 /*-----------------------------------------------------------------*/
3678 /* genCmpGt :- greater than comparison */
3679 /*-----------------------------------------------------------------*/
3681 genCmpGt (iCode * ic, iCode * ifx)
3683 operand *left, *right, *result;
3684 sym_link *letype, *retype;
3687 left = IC_LEFT (ic);
3688 right = IC_RIGHT (ic);
3689 result = IC_RESULT (ic);
3691 letype = getSpec (operandType (left));
3692 retype = getSpec (operandType (right));
3693 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3694 /* assign the amsops */
3695 aopOp (left, ic, FALSE);
3696 aopOp (right, ic, FALSE);
3697 aopOp (result, ic, TRUE);
3699 genCmp (right, left, result, ifx, sign,ic);
3701 freeAsmop (result, NULL, ic, TRUE);
3704 /*-----------------------------------------------------------------*/
3705 /* genCmpLt - less than comparisons */
3706 /*-----------------------------------------------------------------*/
3708 genCmpLt (iCode * ic, iCode * ifx)
3710 operand *left, *right, *result;
3711 sym_link *letype, *retype;
3714 left = IC_LEFT (ic);
3715 right = IC_RIGHT (ic);
3716 result = IC_RESULT (ic);
3718 letype = getSpec (operandType (left));
3719 retype = getSpec (operandType (right));
3720 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3722 /* assign the amsops */
3723 aopOp (left, ic, FALSE);
3724 aopOp (right, ic, FALSE);
3725 aopOp (result, ic, TRUE);
3727 genCmp (left, right, result, ifx, sign,ic);
3729 freeAsmop (result, NULL, ic, TRUE);
3732 /*-----------------------------------------------------------------*/
3733 /* gencjneshort - compare and jump if not equal */
3734 /*-----------------------------------------------------------------*/
3736 gencjneshort (operand * left, operand * right, symbol * lbl)
3738 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3740 unsigned long lit = 0L;
3742 /* if the left side is a literal or
3743 if the right is in a pointer register and left
3745 if ((AOP_TYPE (left) == AOP_LIT) ||
3746 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3752 if (AOP_TYPE (right) == AOP_LIT)
3753 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3755 /* if the right side is a literal then anything goes */
3756 if (AOP_TYPE (right) == AOP_LIT &&
3757 AOP_TYPE (left) != AOP_DIR)
3761 emitcode ("cjne", "%s,%s,%05d$",
3762 aopGet (AOP (left), offset, FALSE, FALSE),
3763 aopGet (AOP (right), offset, FALSE, FALSE),
3769 /* if the right side is in a register or in direct space or
3770 if the left is a pointer register & right is not */
3771 else if (AOP_TYPE (right) == AOP_REG ||
3772 AOP_TYPE (right) == AOP_DIR ||
3773 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3774 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3778 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3779 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3780 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3781 emitcode ("jnz", "%05d$", lbl->key + 100);
3783 emitcode ("cjne", "a,%s,%05d$",
3784 aopGet (AOP (right), offset, FALSE, TRUE),
3791 /* right is a pointer reg need both a & b */
3794 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3795 if (strcmp (l, "b"))
3796 emitcode ("mov", "b,%s", l);
3797 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3798 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3804 /*-----------------------------------------------------------------*/
3805 /* gencjne - compare and jump if not equal */
3806 /*-----------------------------------------------------------------*/
3808 gencjne (operand * left, operand * right, symbol * lbl)
3810 symbol *tlbl = newiTempLabel (NULL);
3812 gencjneshort (left, right, lbl);
3814 emitcode ("mov", "a,%s", one);
3815 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3816 emitcode ("", "%05d$:", lbl->key + 100);
3817 emitcode ("clr", "a");
3818 emitcode ("", "%05d$:", tlbl->key + 100);
3821 /*-----------------------------------------------------------------*/
3822 /* genCmpEq - generates code for equal to */
3823 /*-----------------------------------------------------------------*/
3825 genCmpEq (iCode * ic, iCode * ifx)
3827 operand *left, *right, *result;
3829 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3830 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3831 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3833 /* if literal, literal on the right or
3834 if the right is in a pointer register and left
3836 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3837 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3839 operand *t = IC_RIGHT (ic);
3840 IC_RIGHT (ic) = IC_LEFT (ic);
3844 if (ifx && !AOP_SIZE (result))
3847 /* if they are both bit variables */
3848 if (AOP_TYPE (left) == AOP_CRY &&
3849 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3851 if (AOP_TYPE (right) == AOP_LIT)
3853 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3856 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3857 emitcode ("cpl", "c");
3861 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3865 emitcode ("clr", "c");
3867 /* AOP_TYPE(right) == AOP_CRY */
3871 symbol *lbl = newiTempLabel (NULL);
3872 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3873 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3874 emitcode ("cpl", "c");
3875 emitcode ("", "%05d$:", (lbl->key + 100));
3877 /* if true label then we jump if condition
3879 tlbl = newiTempLabel (NULL);
3882 emitcode ("jnc", "%05d$", tlbl->key + 100);
3883 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3887 emitcode ("jc", "%05d$", tlbl->key + 100);
3888 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3890 emitcode ("", "%05d$:", tlbl->key + 100);
3894 tlbl = newiTempLabel (NULL);
3895 gencjneshort (left, right, tlbl);
3898 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3899 emitcode ("", "%05d$:", tlbl->key + 100);
3903 symbol *lbl = newiTempLabel (NULL);
3904 emitcode ("sjmp", "%05d$", lbl->key + 100);
3905 emitcode ("", "%05d$:", tlbl->key + 100);
3906 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3907 emitcode ("", "%05d$:", lbl->key + 100);
3910 /* mark the icode as generated */
3915 /* if they are both bit variables */
3916 if (AOP_TYPE (left) == AOP_CRY &&
3917 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3919 if (AOP_TYPE (right) == AOP_LIT)
3921 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3924 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3925 emitcode ("cpl", "c");
3929 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3933 emitcode ("clr", "c");
3935 /* AOP_TYPE(right) == AOP_CRY */
3939 symbol *lbl = newiTempLabel (NULL);
3940 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3941 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3942 emitcode ("cpl", "c");
3943 emitcode ("", "%05d$:", (lbl->key + 100));
3946 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3953 genIfxJump (ifx, "c");
3956 /* if the result is used in an arithmetic operation
3957 then put the result in place */
3962 gencjne (left, right, newiTempLabel (NULL));
3963 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3965 aopPut (AOP (result), "a", 0);
3970 genIfxJump (ifx, "a");
3973 /* if the result is used in an arithmetic operation
3974 then put the result in place */
3975 if (AOP_TYPE (result) != AOP_CRY)
3977 /* leave the result in acc */
3981 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3983 freeAsmop (result, NULL, ic, TRUE);
3986 /*-----------------------------------------------------------------*/
3987 /* ifxForOp - returns the icode containing the ifx for operand */
3988 /*-----------------------------------------------------------------*/
3990 ifxForOp (operand * op, iCode * ic)
3992 /* if true symbol then needs to be assigned */
3993 if (IS_TRUE_SYMOP (op))
3996 /* if this has register type condition and
3997 the next instruction is ifx with the same operand
3998 and live to of the operand is upto the ifx only then */
4000 ic->next->op == IFX &&
4001 IC_COND (ic->next)->key == op->key &&
4002 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4008 /*-----------------------------------------------------------------*/
4009 /* hasInc - operand is incremented before any other use */
4010 /*-----------------------------------------------------------------*/
4012 hasInc (operand *op, iCode *ic)
4014 sym_link *type = operandType(op);
4015 sym_link *retype = getSpec (type);
4016 iCode *lic = ic->next;
4019 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4020 isize = getSize(type->next);
4022 /* if operand of the form op = op + <sizeof *op> */
4023 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4024 isOperandEqual(IC_RESULT(lic),op) &&
4025 isOperandLiteral(IC_RIGHT(lic)) &&
4026 operandLitValue(IC_RIGHT(lic)) == isize) {
4029 /* if the operand used or deffed */
4030 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4038 /*-----------------------------------------------------------------*/
4039 /* genAndOp - for && operation */
4040 /*-----------------------------------------------------------------*/
4042 genAndOp (iCode * ic)
4044 operand *left, *right, *result;
4047 /* note here that && operations that are in an
4048 if statement are taken away by backPatchLabels
4049 only those used in arthmetic operations remain */
4050 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4051 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4052 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4054 /* if both are bit variables */
4055 if (AOP_TYPE (left) == AOP_CRY &&
4056 AOP_TYPE (right) == AOP_CRY)
4058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4059 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4064 tlbl = newiTempLabel (NULL);
4066 emitcode ("jz", "%05d$", tlbl->key + 100);
4068 emitcode ("", "%05d$:", tlbl->key + 100);
4072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4073 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4074 freeAsmop (result, NULL, ic, TRUE);
4078 /*-----------------------------------------------------------------*/
4079 /* genOrOp - for || operation */
4080 /*-----------------------------------------------------------------*/
4082 genOrOp (iCode * ic)
4084 operand *left, *right, *result;
4087 /* note here that || operations that are in an
4088 if statement are taken away by backPatchLabels
4089 only those used in arthmetic operations remain */
4090 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4091 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4092 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4094 /* if both are bit variables */
4095 if (AOP_TYPE (left) == AOP_CRY &&
4096 AOP_TYPE (right) == AOP_CRY)
4098 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4099 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4104 tlbl = newiTempLabel (NULL);
4106 emitcode ("jnz", "%05d$", tlbl->key + 100);
4108 emitcode ("", "%05d$:", tlbl->key + 100);
4112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4113 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4114 freeAsmop (result, NULL, ic, TRUE);
4117 /*-----------------------------------------------------------------*/
4118 /* isLiteralBit - test if lit == 2^n */
4119 /*-----------------------------------------------------------------*/
4121 isLiteralBit (unsigned long lit)
4123 unsigned long pw[32] =
4124 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4125 0x100L, 0x200L, 0x400L, 0x800L,
4126 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4127 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4128 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4129 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4130 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4133 for (idx = 0; idx < 32; idx++)
4139 /*-----------------------------------------------------------------*/
4140 /* continueIfTrue - */
4141 /*-----------------------------------------------------------------*/
4143 continueIfTrue (iCode * ic)
4146 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4150 /*-----------------------------------------------------------------*/
4152 /*-----------------------------------------------------------------*/
4154 jumpIfTrue (iCode * ic)
4157 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4161 /*-----------------------------------------------------------------*/
4162 /* jmpTrueOrFalse - */
4163 /*-----------------------------------------------------------------*/
4165 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4167 // ugly but optimized by peephole
4170 symbol *nlbl = newiTempLabel (NULL);
4171 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4172 emitcode ("", "%05d$:", tlbl->key + 100);
4173 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4174 emitcode ("", "%05d$:", nlbl->key + 100);
4178 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4179 emitcode ("", "%05d$:", tlbl->key + 100);
4184 /*-----------------------------------------------------------------*/
4185 /* genAnd - code for and */
4186 /*-----------------------------------------------------------------*/
4188 genAnd (iCode * ic, iCode * ifx)
4190 operand *left, *right, *result;
4191 int size, offset = 0;
4192 unsigned long lit = 0L;
4196 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4197 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4198 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4201 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4203 AOP_TYPE (left), AOP_TYPE (right));
4204 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4206 AOP_SIZE (left), AOP_SIZE (right));
4209 /* if left is a literal & right is not then exchange them */
4210 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4211 AOP_NEEDSACC (left))
4213 operand *tmp = right;
4218 /* if result = right then exchange them */
4219 if (sameRegs (AOP (result), AOP (right)))
4221 operand *tmp = right;
4226 /* if right is bit then exchange them */
4227 if (AOP_TYPE (right) == AOP_CRY &&
4228 AOP_TYPE (left) != AOP_CRY)
4230 operand *tmp = right;
4234 if (AOP_TYPE (right) == AOP_LIT)
4235 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4237 size = AOP_SIZE (result);
4240 // result = bit & yy;
4241 if (AOP_TYPE (left) == AOP_CRY)
4243 // c = bit & literal;
4244 if (AOP_TYPE (right) == AOP_LIT)
4248 if (size && sameRegs (AOP (result), AOP (left)))
4251 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4256 if (size && (AOP_TYPE (result) == AOP_CRY))
4258 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4261 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4266 emitcode ("clr", "c");
4271 if (AOP_TYPE (right) == AOP_CRY)
4274 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4275 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4280 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4282 emitcode ("rrc", "a");
4283 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4291 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4292 genIfxJump (ifx, "c");
4296 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4297 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4298 if ((AOP_TYPE (right) == AOP_LIT) &&
4299 (AOP_TYPE (result) == AOP_CRY) &&
4300 (AOP_TYPE (left) != AOP_CRY))
4302 int posbit = isLiteralBit (lit);
4307 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4310 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4316 sprintf (buffer, "acc.%d", posbit & 0x07);
4317 genIfxJump (ifx, buffer);
4324 symbol *tlbl = newiTempLabel (NULL);
4325 int sizel = AOP_SIZE (left);
4327 emitcode ("setb", "c");
4330 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4332 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4334 if ((posbit = isLiteralBit (bytelit)) != 0)
4335 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4338 if (bytelit != 0x0FFL)
4339 emitcode ("anl", "a,%s",
4340 aopGet (AOP (right), offset, FALSE, TRUE));
4341 emitcode ("jnz", "%05d$", tlbl->key + 100);
4346 // bit = left & literal
4349 emitcode ("clr", "c");
4350 emitcode ("", "%05d$:", tlbl->key + 100);
4352 // if(left & literal)
4356 jmpTrueOrFalse (ifx, tlbl);
4364 /* if left is same as result */
4365 if (sameRegs (AOP (result), AOP (left)))
4367 for (; size--; offset++)
4369 if (AOP_TYPE (right) == AOP_LIT)
4371 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4373 else if (bytelit == 0)
4374 aopPut (AOP (result), zero, offset);
4375 else if (IS_AOP_PREG (result))
4377 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4378 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4379 aopPut (AOP (result), "a", offset);
4382 emitcode ("anl", "%s,%s",
4383 aopGet (AOP (left), offset, FALSE, TRUE),
4384 aopGet (AOP (right), offset, FALSE, FALSE));
4388 if (AOP_TYPE (left) == AOP_ACC)
4389 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4392 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4393 if (IS_AOP_PREG (result))
4395 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4396 aopPut (AOP (result), "a", offset);
4400 emitcode ("anl", "%s,a",
4401 aopGet (AOP (left), offset, FALSE, TRUE));
4408 // left & result in different registers
4409 if (AOP_TYPE (result) == AOP_CRY)
4412 // if(size), result in bit
4413 // if(!size && ifx), conditional oper: if(left & right)
4414 symbol *tlbl = newiTempLabel (NULL);
4415 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4417 emitcode ("setb", "c");
4420 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4421 emitcode ("anl", "a,%s",
4422 aopGet (AOP (left), offset, FALSE, FALSE));
4423 emitcode ("jnz", "%05d$", tlbl->key + 100);
4429 emitcode ("", "%05d$:", tlbl->key + 100);
4433 jmpTrueOrFalse (ifx, tlbl);
4437 for (; (size--); offset++)
4440 // result = left & right
4441 if (AOP_TYPE (right) == AOP_LIT)
4443 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4445 aopPut (AOP (result),
4446 aopGet (AOP (left), offset, FALSE, FALSE),
4450 else if (bytelit == 0)
4452 aopPut (AOP (result), zero, offset);
4456 // faster than result <- left, anl result,right
4457 // and better if result is SFR
4458 if (AOP_TYPE (left) == AOP_ACC)
4459 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4462 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4463 emitcode ("anl", "a,%s",
4464 aopGet (AOP (left), offset, FALSE, FALSE));
4466 aopPut (AOP (result), "a", offset);
4472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474 freeAsmop (result, NULL, ic, TRUE);
4477 /*-----------------------------------------------------------------*/
4478 /* genOr - code for or */
4479 /*-----------------------------------------------------------------*/
4481 genOr (iCode * ic, iCode * ifx)
4483 operand *left, *right, *result;
4484 int size, offset = 0;
4485 unsigned long lit = 0L;
4487 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4488 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4489 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4492 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4494 AOP_TYPE (left), AOP_TYPE (right));
4495 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4497 AOP_SIZE (left), AOP_SIZE (right));
4500 /* if left is a literal & right is not then exchange them */
4501 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4502 AOP_NEEDSACC (left))
4504 operand *tmp = right;
4509 /* if result = right then exchange them */
4510 if (sameRegs (AOP (result), AOP (right)))
4512 operand *tmp = right;
4517 /* if right is bit then exchange them */
4518 if (AOP_TYPE (right) == AOP_CRY &&
4519 AOP_TYPE (left) != AOP_CRY)
4521 operand *tmp = right;
4525 if (AOP_TYPE (right) == AOP_LIT)
4526 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4528 size = AOP_SIZE (result);
4532 if (AOP_TYPE (left) == AOP_CRY)
4534 if (AOP_TYPE (right) == AOP_LIT)
4536 // c = bit & literal;
4539 // lit != 0 => result = 1
4540 if (AOP_TYPE (result) == AOP_CRY)
4543 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4545 continueIfTrue (ifx);
4548 emitcode ("setb", "c");
4552 // lit == 0 => result = left
4553 if (size && sameRegs (AOP (result), AOP (left)))
4555 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4560 if (AOP_TYPE (right) == AOP_CRY)
4563 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4564 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4569 symbol *tlbl = newiTempLabel (NULL);
4570 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4571 emitcode ("setb", "c");
4572 emitcode ("jb", "%s,%05d$",
4573 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4575 emitcode ("jnz", "%05d$", tlbl->key + 100);
4576 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4578 jmpTrueOrFalse (ifx, tlbl);
4584 emitcode ("", "%05d$:", tlbl->key + 100);
4593 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4594 genIfxJump (ifx, "c");
4598 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4599 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4600 if ((AOP_TYPE (right) == AOP_LIT) &&
4601 (AOP_TYPE (result) == AOP_CRY) &&
4602 (AOP_TYPE (left) != AOP_CRY))
4608 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4610 continueIfTrue (ifx);
4615 // lit = 0, result = boolean(left)
4617 emitcode ("setb", "c");
4621 symbol *tlbl = newiTempLabel (NULL);
4622 emitcode ("jnz", "%05d$", tlbl->key + 100);
4624 emitcode ("", "%05d$:", tlbl->key + 100);
4628 genIfxJump (ifx, "a");
4636 /* if left is same as result */
4637 if (sameRegs (AOP (result), AOP (left)))
4639 for (; size--; offset++)
4641 if (AOP_TYPE (right) == AOP_LIT)
4643 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4645 else if (IS_AOP_PREG (left))
4647 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4648 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4649 aopPut (AOP (result), "a", offset);
4652 emitcode ("orl", "%s,%s",
4653 aopGet (AOP (left), offset, FALSE, TRUE),
4654 aopGet (AOP (right), offset, FALSE, FALSE));
4658 if (AOP_TYPE (left) == AOP_ACC)
4659 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4662 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4663 if (IS_AOP_PREG (left))
4665 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4666 aopPut (AOP (result), "a", offset);
4669 emitcode ("orl", "%s,a",
4670 aopGet (AOP (left), offset, FALSE, TRUE));
4677 // left & result in different registers
4678 if (AOP_TYPE (result) == AOP_CRY)
4681 // if(size), result in bit
4682 // if(!size && ifx), conditional oper: if(left | right)
4683 symbol *tlbl = newiTempLabel (NULL);
4684 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4686 emitcode ("setb", "c");
4689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4690 emitcode ("orl", "a,%s",
4691 aopGet (AOP (left), offset, FALSE, FALSE));
4692 emitcode ("jnz", "%05d$", tlbl->key + 100);
4698 emitcode ("", "%05d$:", tlbl->key + 100);
4702 jmpTrueOrFalse (ifx, tlbl);
4705 for (; (size--); offset++)
4708 // result = left & right
4709 if (AOP_TYPE (right) == AOP_LIT)
4711 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4713 aopPut (AOP (result),
4714 aopGet (AOP (left), offset, FALSE, FALSE),
4719 // faster than result <- left, anl result,right
4720 // and better if result is SFR
4721 if (AOP_TYPE (left) == AOP_ACC)
4722 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4725 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4726 emitcode ("orl", "a,%s",
4727 aopGet (AOP (left), offset, FALSE, FALSE));
4729 aopPut (AOP (result), "a", offset);
4734 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736 freeAsmop (result, NULL, ic, TRUE);
4739 /*-----------------------------------------------------------------*/
4740 /* genXor - code for xclusive or */
4741 /*-----------------------------------------------------------------*/
4743 genXor (iCode * ic, iCode * ifx)
4745 operand *left, *right, *result;
4746 int size, offset = 0;
4747 unsigned long lit = 0L;
4749 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4750 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4751 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4754 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4756 AOP_TYPE (left), AOP_TYPE (right));
4757 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4759 AOP_SIZE (left), AOP_SIZE (right));
4762 /* if left is a literal & right is not ||
4763 if left needs acc & right does not */
4764 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4765 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4767 operand *tmp = right;
4772 /* if result = right then exchange them */
4773 if (sameRegs (AOP (result), AOP (right)))
4775 operand *tmp = right;
4780 /* if right is bit then exchange them */
4781 if (AOP_TYPE (right) == AOP_CRY &&
4782 AOP_TYPE (left) != AOP_CRY)
4784 operand *tmp = right;
4788 if (AOP_TYPE (right) == AOP_LIT)
4789 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4791 size = AOP_SIZE (result);
4795 if (AOP_TYPE (left) == AOP_CRY)
4797 if (AOP_TYPE (right) == AOP_LIT)
4799 // c = bit & literal;
4802 // lit>>1 != 0 => result = 1
4803 if (AOP_TYPE (result) == AOP_CRY)
4806 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4808 continueIfTrue (ifx);
4811 emitcode ("setb", "c");
4818 // lit == 0, result = left
4819 if (size && sameRegs (AOP (result), AOP (left)))
4821 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4825 // lit == 1, result = not(left)
4826 if (size && sameRegs (AOP (result), AOP (left)))
4828 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4833 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4834 emitcode ("cpl", "c");
4843 symbol *tlbl = newiTempLabel (NULL);
4844 if (AOP_TYPE (right) == AOP_CRY)
4847 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4851 int sizer = AOP_SIZE (right);
4853 // if val>>1 != 0, result = 1
4854 emitcode ("setb", "c");
4857 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4859 // test the msb of the lsb
4860 emitcode ("anl", "a,#0xfe");
4861 emitcode ("jnz", "%05d$", tlbl->key + 100);
4865 emitcode ("rrc", "a");
4867 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4868 emitcode ("cpl", "c");
4869 emitcode ("", "%05d$:", (tlbl->key + 100));
4876 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4877 genIfxJump (ifx, "c");
4881 if (sameRegs (AOP (result), AOP (left)))
4883 /* if left is same as result */
4884 for (; size--; offset++)
4886 if (AOP_TYPE (right) == AOP_LIT)
4888 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4890 else if (IS_AOP_PREG (left))
4892 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4893 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4894 aopPut (AOP (result), "a", offset);
4897 emitcode ("xrl", "%s,%s",
4898 aopGet (AOP (left), offset, FALSE, TRUE),
4899 aopGet (AOP (right), offset, FALSE, FALSE));
4903 if (AOP_TYPE (left) == AOP_ACC)
4904 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4908 if (IS_AOP_PREG (left))
4910 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4911 aopPut (AOP (result), "a", offset);
4914 emitcode ("xrl", "%s,a",
4915 aopGet (AOP (left), offset, FALSE, TRUE));
4922 // left & result in different registers
4923 if (AOP_TYPE (result) == AOP_CRY)
4926 // if(size), result in bit
4927 // if(!size && ifx), conditional oper: if(left ^ right)
4928 symbol *tlbl = newiTempLabel (NULL);
4929 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4931 emitcode ("setb", "c");
4934 if ((AOP_TYPE (right) == AOP_LIT) &&
4935 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4937 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4941 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4942 emitcode ("xrl", "a,%s",
4943 aopGet (AOP (left), offset, FALSE, FALSE));
4945 emitcode ("jnz", "%05d$", tlbl->key + 100);
4951 emitcode ("", "%05d$:", tlbl->key + 100);
4955 jmpTrueOrFalse (ifx, tlbl);
4958 for (; (size--); offset++)
4961 // result = left & right
4962 if (AOP_TYPE (right) == AOP_LIT)
4964 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4966 aopPut (AOP (result),
4967 aopGet (AOP (left), offset, FALSE, FALSE),
4972 // faster than result <- left, anl result,right
4973 // and better if result is SFR
4974 if (AOP_TYPE (left) == AOP_ACC)
4975 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4979 emitcode ("xrl", "a,%s",
4980 aopGet (AOP (left), offset, FALSE, TRUE));
4982 aopPut (AOP (result), "a", offset);
4987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4989 freeAsmop (result, NULL, ic, TRUE);
4992 /*-----------------------------------------------------------------*/
4993 /* genInline - write the inline code out */
4994 /*-----------------------------------------------------------------*/
4997 genInline (iCode * ic)
4999 char *buffer, *bp, *bp1;
5001 _G.inLine += (!options.asmpeep);
5003 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5004 strcpy (buffer, IC_INLINE (ic));
5006 /* emit each line as a code */
5033 /* emitcode("",buffer); */
5034 _G.inLine -= (!options.asmpeep);
5037 /*-----------------------------------------------------------------*/
5038 /* genRRC - rotate right with carry */
5039 /*-----------------------------------------------------------------*/
5043 operand *left, *result;
5044 int size, offset = 0;
5047 /* rotate right with carry */
5048 left = IC_LEFT (ic);
5049 result = IC_RESULT (ic);
5050 aopOp (left, ic, FALSE);
5051 aopOp (result, ic, FALSE);
5053 /* move it to the result */
5054 size = AOP_SIZE (result);
5059 l = aopGet (AOP (left), offset, FALSE, FALSE);
5061 emitcode ("rrc", "a");
5062 if (AOP_SIZE (result) > 1)
5063 aopPut (AOP (result), "a", offset--);
5065 /* now we need to put the carry into the
5066 highest order byte of the result */
5067 if (AOP_SIZE (result) > 1)
5069 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5072 emitcode ("mov", "acc.7,c");
5073 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5074 freeAsmop (left, NULL, ic, TRUE);
5075 freeAsmop (result, NULL, ic, TRUE);
5078 /*-----------------------------------------------------------------*/
5079 /* genRLC - generate code for rotate left with carry */
5080 /*-----------------------------------------------------------------*/
5084 operand *left, *result;
5085 int size, offset = 0;
5088 /* rotate right with carry */
5089 left = IC_LEFT (ic);
5090 result = IC_RESULT (ic);
5091 aopOp (left, ic, FALSE);
5092 aopOp (result, ic, FALSE);
5094 /* move it to the result */
5095 size = AOP_SIZE (result);
5099 l = aopGet (AOP (left), offset, FALSE, FALSE);
5101 emitcode ("add", "a,acc");
5102 if (AOP_SIZE (result) > 1)
5103 aopPut (AOP (result), "a", offset++);
5106 l = aopGet (AOP (left), offset, FALSE, FALSE);
5108 emitcode ("rlc", "a");
5109 if (AOP_SIZE (result) > 1)
5110 aopPut (AOP (result), "a", offset++);
5113 /* now we need to put the carry into the
5114 highest order byte of the result */
5115 if (AOP_SIZE (result) > 1)
5117 l = aopGet (AOP (result), 0, FALSE, FALSE);
5120 emitcode ("mov", "acc.0,c");
5121 aopPut (AOP (result), "a", 0);
5122 freeAsmop (left, NULL, ic, TRUE);
5123 freeAsmop (result, NULL, ic, TRUE);
5126 /*-----------------------------------------------------------------*/
5127 /* genGetHbit - generates code get highest order bit */
5128 /*-----------------------------------------------------------------*/
5130 genGetHbit (iCode * ic)
5132 operand *left, *result;
5133 left = IC_LEFT (ic);
5134 result = IC_RESULT (ic);
5135 aopOp (left, ic, FALSE);
5136 aopOp (result, ic, FALSE);
5138 /* get the highest order byte into a */
5139 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5140 if (AOP_TYPE (result) == AOP_CRY)
5142 emitcode ("rlc", "a");
5147 emitcode ("rl", "a");
5148 emitcode ("anl", "a,#0x01");
5153 freeAsmop (left, NULL, ic, TRUE);
5154 freeAsmop (result, NULL, ic, TRUE);
5157 /*-----------------------------------------------------------------*/
5158 /* AccRol - rotate left accumulator by known count */
5159 /*-----------------------------------------------------------------*/
5161 AccRol (int shCount)
5163 shCount &= 0x0007; // shCount : 0..7
5170 emitcode ("rl", "a");
5173 emitcode ("rl", "a");
5174 emitcode ("rl", "a");
5177 emitcode ("swap", "a");
5178 emitcode ("rr", "a");
5181 emitcode ("swap", "a");
5184 emitcode ("swap", "a");
5185 emitcode ("rl", "a");
5188 emitcode ("rr", "a");
5189 emitcode ("rr", "a");
5192 emitcode ("rr", "a");
5197 /*-----------------------------------------------------------------*/
5198 /* AccLsh - left shift accumulator by known count */
5199 /*-----------------------------------------------------------------*/
5201 AccLsh (int shCount)
5206 emitcode ("add", "a,acc");
5207 else if (shCount == 2)
5209 emitcode ("add", "a,acc");
5210 emitcode ("add", "a,acc");
5214 /* rotate left accumulator */
5216 /* and kill the lower order bits */
5217 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5222 /*-----------------------------------------------------------------*/
5223 /* AccRsh - right shift accumulator by known count */
5224 /*-----------------------------------------------------------------*/
5226 AccRsh (int shCount)
5233 emitcode ("rrc", "a");
5237 /* rotate right accumulator */
5238 AccRol (8 - shCount);
5239 /* and kill the higher order bits */
5240 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5245 /*-----------------------------------------------------------------*/
5246 /* AccSRsh - signed right shift accumulator by known count */
5247 /*-----------------------------------------------------------------*/
5249 AccSRsh (int shCount)
5256 emitcode ("mov", "c,acc.7");
5257 emitcode ("rrc", "a");
5259 else if (shCount == 2)
5261 emitcode ("mov", "c,acc.7");
5262 emitcode ("rrc", "a");
5263 emitcode ("mov", "c,acc.7");
5264 emitcode ("rrc", "a");
5268 tlbl = newiTempLabel (NULL);
5269 /* rotate right accumulator */
5270 AccRol (8 - shCount);
5271 /* and kill the higher order bits */
5272 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5273 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5274 emitcode ("orl", "a,#0x%02x",
5275 (unsigned char) ~SRMask[shCount]);
5276 emitcode ("", "%05d$:", tlbl->key + 100);
5281 /*-----------------------------------------------------------------*/
5282 /* shiftR1Left2Result - shift right one byte from left to result */
5283 /*-----------------------------------------------------------------*/
5285 shiftR1Left2Result (operand * left, int offl,
5286 operand * result, int offr,
5287 int shCount, int sign)
5289 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5290 /* shift right accumulator */
5295 aopPut (AOP (result), "a", offr);
5298 /*-----------------------------------------------------------------*/
5299 /* shiftL1Left2Result - shift left one byte from left to result */
5300 /*-----------------------------------------------------------------*/
5302 shiftL1Left2Result (operand * left, int offl,
5303 operand * result, int offr, int shCount)
5306 l = aopGet (AOP (left), offl, FALSE, FALSE);
5308 /* shift left accumulator */
5310 aopPut (AOP (result), "a", offr);
5313 /*-----------------------------------------------------------------*/
5314 /* movLeft2Result - move byte from left to result */
5315 /*-----------------------------------------------------------------*/
5317 movLeft2Result (operand * left, int offl,
5318 operand * result, int offr, int sign)
5321 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5323 l = aopGet (AOP (left), offl, FALSE, FALSE);
5325 if (*l == '@' && (IS_AOP_PREG (result)))
5327 emitcode ("mov", "a,%s", l);
5328 aopPut (AOP (result), "a", offr);
5333 aopPut (AOP (result), l, offr);
5336 /* MSB sign in acc.7 ! */
5337 if (getDataSize (left) == offl + 1)
5339 emitcode ("mov", "a,%s", l);
5340 aopPut (AOP (result), "a", offr);
5347 /*-----------------------------------------------------------------*/
5348 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5349 /*-----------------------------------------------------------------*/
5353 emitcode ("rrc", "a");
5354 emitcode ("xch", "a,%s", x);
5355 emitcode ("rrc", "a");
5356 emitcode ("xch", "a,%s", x);
5359 /*-----------------------------------------------------------------*/
5360 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5361 /*-----------------------------------------------------------------*/
5365 emitcode ("xch", "a,%s", x);
5366 emitcode ("rlc", "a");
5367 emitcode ("xch", "a,%s", x);
5368 emitcode ("rlc", "a");
5371 /*-----------------------------------------------------------------*/
5372 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5373 /*-----------------------------------------------------------------*/
5377 emitcode ("xch", "a,%s", x);
5378 emitcode ("add", "a,acc");
5379 emitcode ("xch", "a,%s", x);
5380 emitcode ("rlc", "a");
5383 /*-----------------------------------------------------------------*/
5384 /* AccAXLsh - left shift a:x by known count (0..7) */
5385 /*-----------------------------------------------------------------*/
5387 AccAXLsh (char *x, int shCount)
5402 case 5: // AAAAABBB:CCCCCDDD
5404 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5406 emitcode ("anl", "a,#0x%02x",
5407 SLMask[shCount]); // BBB00000:CCCCCDDD
5409 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5411 AccRol (shCount); // DDDCCCCC:BBB00000
5413 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5415 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5417 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5419 emitcode ("anl", "a,#0x%02x",
5420 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5422 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5424 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5427 case 6: // AAAAAABB:CCCCCCDD
5428 emitcode ("anl", "a,#0x%02x",
5429 SRMask[shCount]); // 000000BB:CCCCCCDD
5430 emitcode ("mov", "c,acc.0"); // c = B
5431 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5433 AccAXRrl1 (x); // BCCCCCCD:D000000B
5434 AccAXRrl1 (x); // BBCCCCCC:DD000000
5436 emitcode("rrc","a");
5437 emitcode("xch","a,%s", x);
5438 emitcode("rrc","a");
5439 emitcode("mov","c,acc.0"); //<< get correct bit
5440 emitcode("xch","a,%s", x);
5442 emitcode("rrc","a");
5443 emitcode("xch","a,%s", x);
5444 emitcode("rrc","a");
5445 emitcode("xch","a,%s", x);
5448 case 7: // a:x <<= 7
5450 emitcode ("anl", "a,#0x%02x",
5451 SRMask[shCount]); // 0000000B:CCCCCCCD
5453 emitcode ("mov", "c,acc.0"); // c = B
5455 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5457 AccAXRrl1 (x); // BCCCCCCC:D0000000
5465 /*-----------------------------------------------------------------*/
5466 /* AccAXRsh - right shift a:x known count (0..7) */
5467 /*-----------------------------------------------------------------*/
5469 AccAXRsh (char *x, int shCount)
5477 AccAXRrl1 (x); // 0->a:x
5482 AccAXRrl1 (x); // 0->a:x
5485 AccAXRrl1 (x); // 0->a:x
5490 case 5: // AAAAABBB:CCCCCDDD = a:x
5492 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5494 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5496 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5498 emitcode ("anl", "a,#0x%02x",
5499 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5501 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5503 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5505 emitcode ("anl", "a,#0x%02x",
5506 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5508 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5510 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5512 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5515 case 6: // AABBBBBB:CCDDDDDD
5517 emitcode ("mov", "c,acc.7");
5518 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5520 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5522 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5524 emitcode ("anl", "a,#0x%02x",
5525 SRMask[shCount]); // 000000AA:BBBBBBCC
5528 case 7: // ABBBBBBB:CDDDDDDD
5530 emitcode ("mov", "c,acc.7"); // c = A
5532 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5534 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5536 emitcode ("anl", "a,#0x%02x",
5537 SRMask[shCount]); // 0000000A:BBBBBBBC
5545 /*-----------------------------------------------------------------*/
5546 /* AccAXRshS - right shift signed a:x known count (0..7) */
5547 /*-----------------------------------------------------------------*/
5549 AccAXRshS (char *x, int shCount)
5557 emitcode ("mov", "c,acc.7");
5558 AccAXRrl1 (x); // s->a:x
5562 emitcode ("mov", "c,acc.7");
5563 AccAXRrl1 (x); // s->a:x
5565 emitcode ("mov", "c,acc.7");
5566 AccAXRrl1 (x); // s->a:x
5571 case 5: // AAAAABBB:CCCCCDDD = a:x
5573 tlbl = newiTempLabel (NULL);
5574 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5576 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5578 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5580 emitcode ("anl", "a,#0x%02x",
5581 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5583 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5585 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5587 emitcode ("anl", "a,#0x%02x",
5588 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5590 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5592 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5594 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5596 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5597 emitcode ("orl", "a,#0x%02x",
5598 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5600 emitcode ("", "%05d$:", tlbl->key + 100);
5601 break; // SSSSAAAA:BBBCCCCC
5603 case 6: // AABBBBBB:CCDDDDDD
5605 tlbl = newiTempLabel (NULL);
5606 emitcode ("mov", "c,acc.7");
5607 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5609 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5611 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5613 emitcode ("anl", "a,#0x%02x",
5614 SRMask[shCount]); // 000000AA:BBBBBBCC
5616 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5617 emitcode ("orl", "a,#0x%02x",
5618 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5620 emitcode ("", "%05d$:", tlbl->key + 100);
5622 case 7: // ABBBBBBB:CDDDDDDD
5624 tlbl = newiTempLabel (NULL);
5625 emitcode ("mov", "c,acc.7"); // c = A
5627 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5629 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5631 emitcode ("anl", "a,#0x%02x",
5632 SRMask[shCount]); // 0000000A:BBBBBBBC
5634 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5635 emitcode ("orl", "a,#0x%02x",
5636 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5638 emitcode ("", "%05d$:", tlbl->key + 100);
5645 /*-----------------------------------------------------------------*/
5646 /* shiftL2Left2Result - shift left two bytes from left to result */
5647 /*-----------------------------------------------------------------*/
5649 shiftL2Left2Result (operand * left, int offl,
5650 operand * result, int offr, int shCount)
5652 if (sameRegs (AOP (result), AOP (left)) &&
5653 ((offl + MSB16) == offr))
5655 /* don't crash result[offr] */
5656 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5657 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5661 movLeft2Result (left, offl, result, offr, 0);
5662 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5664 /* ax << shCount (x = lsb(result)) */
5665 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5666 aopPut (AOP (result), "a", offr + MSB16);
5670 /*-----------------------------------------------------------------*/
5671 /* shiftR2Left2Result - shift right two bytes from left to result */
5672 /*-----------------------------------------------------------------*/
5674 shiftR2Left2Result (operand * left, int offl,
5675 operand * result, int offr,
5676 int shCount, int sign)
5678 if (sameRegs (AOP (result), AOP (left)) &&
5679 ((offl + MSB16) == offr))
5681 /* don't crash result[offr] */
5682 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5683 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5687 movLeft2Result (left, offl, result, offr, 0);
5688 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5690 /* a:x >> shCount (x = lsb(result)) */
5692 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5694 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5695 if (getDataSize (result) > 1)
5696 aopPut (AOP (result), "a", offr + MSB16);
5699 /*-----------------------------------------------------------------*/
5700 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5701 /*-----------------------------------------------------------------*/
5703 shiftLLeftOrResult (operand * left, int offl,
5704 operand * result, int offr, int shCount)
5706 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5707 /* shift left accumulator */
5709 /* or with result */
5710 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5711 /* back to result */
5712 aopPut (AOP (result), "a", offr);
5715 /*-----------------------------------------------------------------*/
5716 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5717 /*-----------------------------------------------------------------*/
5719 shiftRLeftOrResult (operand * left, int offl,
5720 operand * result, int offr, int shCount)
5722 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5723 /* shift right accumulator */
5725 /* or with result */
5726 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5727 /* back to result */
5728 aopPut (AOP (result), "a", offr);
5731 /*-----------------------------------------------------------------*/
5732 /* genlshOne - left shift a one byte quantity by known count */
5733 /*-----------------------------------------------------------------*/
5735 genlshOne (operand * result, operand * left, int shCount)
5737 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5740 /*-----------------------------------------------------------------*/
5741 /* genlshTwo - left shift two bytes by known amount != 0 */
5742 /*-----------------------------------------------------------------*/
5744 genlshTwo (operand * result, operand * left, int shCount)
5748 size = getDataSize (result);
5750 /* if shCount >= 8 */
5758 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5760 movLeft2Result (left, LSB, result, MSB16, 0);
5762 aopPut (AOP (result), zero, LSB);
5765 /* 1 <= shCount <= 7 */
5769 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5771 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5775 /*-----------------------------------------------------------------*/
5776 /* shiftLLong - shift left one long from left to result */
5777 /* offl = LSB or MSB16 */
5778 /*-----------------------------------------------------------------*/
5780 shiftLLong (operand * left, operand * result, int offr)
5783 int size = AOP_SIZE (result);
5785 if (size >= LSB + offr)
5787 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5789 emitcode ("add", "a,acc");
5790 if (sameRegs (AOP (left), AOP (result)) &&
5791 size >= MSB16 + offr && offr != LSB)
5792 emitcode ("xch", "a,%s",
5793 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5795 aopPut (AOP (result), "a", LSB + offr);
5798 if (size >= MSB16 + offr)
5800 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5802 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5805 emitcode ("rlc", "a");
5806 if (sameRegs (AOP (left), AOP (result)) &&
5807 size >= MSB24 + offr && offr != LSB)
5808 emitcode ("xch", "a,%s",
5809 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5811 aopPut (AOP (result), "a", MSB16 + offr);
5814 if (size >= MSB24 + offr)
5816 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5818 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5821 emitcode ("rlc", "a");
5822 if (sameRegs (AOP (left), AOP (result)) &&
5823 size >= MSB32 + offr && offr != LSB)
5824 emitcode ("xch", "a,%s",
5825 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5827 aopPut (AOP (result), "a", MSB24 + offr);
5830 if (size > MSB32 + offr)
5832 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5834 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5837 emitcode ("rlc", "a");
5838 aopPut (AOP (result), "a", MSB32 + offr);
5841 aopPut (AOP (result), zero, LSB);
5844 /*-----------------------------------------------------------------*/
5845 /* genlshFour - shift four byte by a known amount != 0 */
5846 /*-----------------------------------------------------------------*/
5848 genlshFour (operand * result, operand * left, int shCount)
5852 size = AOP_SIZE (result);
5854 /* if shifting more that 3 bytes */
5859 /* lowest order of left goes to the highest
5860 order of the destination */
5861 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5863 movLeft2Result (left, LSB, result, MSB32, 0);
5864 aopPut (AOP (result), zero, LSB);
5865 aopPut (AOP (result), zero, MSB16);
5866 aopPut (AOP (result), zero, MSB24);
5870 /* more than two bytes */
5871 else if (shCount >= 16)
5873 /* lower order two bytes goes to higher order two bytes */
5875 /* if some more remaining */
5877 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5880 movLeft2Result (left, MSB16, result, MSB32, 0);
5881 movLeft2Result (left, LSB, result, MSB24, 0);
5883 aopPut (AOP (result), zero, MSB16);
5884 aopPut (AOP (result), zero, LSB);
5888 /* if more than 1 byte */
5889 else if (shCount >= 8)
5891 /* lower order three bytes goes to higher order three bytes */
5896 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5898 movLeft2Result (left, LSB, result, MSB16, 0);
5904 movLeft2Result (left, MSB24, result, MSB32, 0);
5905 movLeft2Result (left, MSB16, result, MSB24, 0);
5906 movLeft2Result (left, LSB, result, MSB16, 0);
5907 aopPut (AOP (result), zero, LSB);
5909 else if (shCount == 1)
5910 shiftLLong (left, result, MSB16);
5913 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5914 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5915 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5916 aopPut (AOP (result), zero, LSB);
5921 /* 1 <= shCount <= 7 */
5922 else if (shCount <= 2)
5924 shiftLLong (left, result, LSB);
5926 shiftLLong (result, result, LSB);
5928 /* 3 <= shCount <= 7, optimize */
5931 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5932 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5933 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5937 /*-----------------------------------------------------------------*/
5938 /* genLeftShiftLiteral - left shifting by known count */
5939 /*-----------------------------------------------------------------*/
5941 genLeftShiftLiteral (operand * left,
5946 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5949 freeAsmop (right, NULL, ic, TRUE);
5951 aopOp (left, ic, FALSE);
5952 aopOp (result, ic, FALSE);
5954 size = getSize (operandType (result));
5957 emitcode ("; shift left ", "result %d, left %d", size,
5961 /* I suppose that the left size >= result size */
5966 movLeft2Result (left, size, result, size, 0);
5970 else if (shCount >= (size * 8))
5972 aopPut (AOP (result), zero, size);
5978 genlshOne (result, left, shCount);
5983 genlshTwo (result, left, shCount);
5987 genlshFour (result, left, shCount);
5991 freeAsmop (left, NULL, ic, TRUE);
5992 freeAsmop (result, NULL, ic, TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genLeftShift - generates code for left shifting */
5997 /*-----------------------------------------------------------------*/
5999 genLeftShift (iCode * ic)
6001 operand *left, *right, *result;
6004 symbol *tlbl, *tlbl1;
6006 right = IC_RIGHT (ic);
6007 left = IC_LEFT (ic);
6008 result = IC_RESULT (ic);
6010 aopOp (right, ic, FALSE);
6012 /* if the shift count is known then do it
6013 as efficiently as possible */
6014 if (AOP_TYPE (right) == AOP_LIT)
6016 genLeftShiftLiteral (left, right, result, ic);
6020 /* shift count is unknown then we have to form
6021 a loop get the loop count in B : Note: we take
6022 only the lower order byte since shifting
6023 more that 32 bits make no sense anyway, ( the
6024 largest size of an object can be only 32 bits ) */
6026 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6027 emitcode ("inc", "b");
6028 freeAsmop (right, NULL, ic, TRUE);
6029 aopOp (left, ic, FALSE);
6030 aopOp (result, ic, FALSE);
6032 /* now move the left to the result if they are not the
6034 if (!sameRegs (AOP (left), AOP (result)) &&
6035 AOP_SIZE (result) > 1)
6038 size = AOP_SIZE (result);
6042 l = aopGet (AOP (left), offset, FALSE, TRUE);
6043 if (*l == '@' && (IS_AOP_PREG (result)))
6046 emitcode ("mov", "a,%s", l);
6047 aopPut (AOP (result), "a", offset);
6050 aopPut (AOP (result), l, offset);
6055 tlbl = newiTempLabel (NULL);
6056 size = AOP_SIZE (result);
6058 tlbl1 = newiTempLabel (NULL);
6060 /* if it is only one byte then */
6063 symbol *tlbl1 = newiTempLabel (NULL);
6065 l = aopGet (AOP (left), 0, FALSE, FALSE);
6067 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6068 emitcode ("", "%05d$:", tlbl->key + 100);
6069 emitcode ("add", "a,acc");
6070 emitcode ("", "%05d$:", tlbl1->key + 100);
6071 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6072 aopPut (AOP (result), "a", 0);
6076 reAdjustPreg (AOP (result));
6078 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6079 emitcode ("", "%05d$:", tlbl->key + 100);
6080 l = aopGet (AOP (result), offset, FALSE, FALSE);
6082 emitcode ("add", "a,acc");
6083 aopPut (AOP (result), "a", offset++);
6086 l = aopGet (AOP (result), offset, FALSE, FALSE);
6088 emitcode ("rlc", "a");
6089 aopPut (AOP (result), "a", offset++);
6091 reAdjustPreg (AOP (result));
6093 emitcode ("", "%05d$:", tlbl1->key + 100);
6094 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6096 freeAsmop (left, NULL, ic, TRUE);
6097 freeAsmop (result, NULL, ic, TRUE);
6100 /*-----------------------------------------------------------------*/
6101 /* genrshOne - right shift a one byte quantity by known count */
6102 /*-----------------------------------------------------------------*/
6104 genrshOne (operand * result, operand * left,
6105 int shCount, int sign)
6107 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6110 /*-----------------------------------------------------------------*/
6111 /* genrshTwo - right shift two bytes by known amount != 0 */
6112 /*-----------------------------------------------------------------*/
6114 genrshTwo (operand * result, operand * left,
6115 int shCount, int sign)
6117 /* if shCount >= 8 */
6122 shiftR1Left2Result (left, MSB16, result, LSB,
6125 movLeft2Result (left, MSB16, result, LSB, sign);
6126 addSign (result, MSB16, sign);
6129 /* 1 <= shCount <= 7 */
6131 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6134 /*-----------------------------------------------------------------*/
6135 /* shiftRLong - shift right one long from left to result */
6136 /* offl = LSB or MSB16 */
6137 /*-----------------------------------------------------------------*/
6139 shiftRLong (operand * left, int offl,
6140 operand * result, int sign)
6143 emitcode ("clr", "c");
6144 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6146 emitcode ("mov", "c,acc.7");
6147 emitcode ("rrc", "a");
6148 aopPut (AOP (result), "a", MSB32 - offl);
6150 /* add sign of "a" */
6151 addSign (result, MSB32, sign);
6153 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6154 emitcode ("rrc", "a");
6155 aopPut (AOP (result), "a", MSB24 - offl);
6157 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6158 emitcode ("rrc", "a");
6159 aopPut (AOP (result), "a", MSB16 - offl);
6163 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6164 emitcode ("rrc", "a");
6165 aopPut (AOP (result), "a", LSB);
6169 /*-----------------------------------------------------------------*/
6170 /* genrshFour - shift four byte by a known amount != 0 */
6171 /*-----------------------------------------------------------------*/
6173 genrshFour (operand * result, operand * left,
6174 int shCount, int sign)
6176 /* if shifting more that 3 bytes */
6181 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6183 movLeft2Result (left, MSB32, result, LSB, sign);
6184 addSign (result, MSB16, sign);
6186 else if (shCount >= 16)
6190 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6193 movLeft2Result (left, MSB24, result, LSB, 0);
6194 movLeft2Result (left, MSB32, result, MSB16, sign);
6196 addSign (result, MSB24, sign);
6198 else if (shCount >= 8)
6202 shiftRLong (left, MSB16, result, sign);
6203 else if (shCount == 0)
6205 movLeft2Result (left, MSB16, result, LSB, 0);
6206 movLeft2Result (left, MSB24, result, MSB16, 0);
6207 movLeft2Result (left, MSB32, result, MSB24, sign);
6208 addSign (result, MSB32, sign);
6212 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6213 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6214 /* the last shift is signed */
6215 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6216 addSign (result, MSB32, sign);
6220 { /* 1 <= shCount <= 7 */
6223 shiftRLong (left, LSB, result, sign);
6225 shiftRLong (result, LSB, result, sign);
6229 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6230 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6231 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6236 /*-----------------------------------------------------------------*/
6237 /* genRightShiftLiteral - right shifting by known count */
6238 /*-----------------------------------------------------------------*/
6240 genRightShiftLiteral (operand * left,
6246 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6249 freeAsmop (right, NULL, ic, TRUE);
6251 aopOp (left, ic, FALSE);
6252 aopOp (result, ic, FALSE);
6255 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6259 size = getDataSize (left);
6260 /* test the LEFT size !!! */
6262 /* I suppose that the left size >= result size */
6265 size = getDataSize (result);
6267 movLeft2Result (left, size, result, size, 0);
6270 else if (shCount >= (size * 8))
6273 /* get sign in acc.7 */
6274 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6275 addSign (result, LSB, sign);
6282 genrshOne (result, left, shCount, sign);
6286 genrshTwo (result, left, shCount, sign);
6290 genrshFour (result, left, shCount, sign);
6296 freeAsmop (left, NULL, ic, TRUE);
6297 freeAsmop (result, NULL, ic, TRUE);
6301 /*-----------------------------------------------------------------*/
6302 /* genSignedRightShift - right shift of signed number */
6303 /*-----------------------------------------------------------------*/
6305 genSignedRightShift (iCode * ic)
6307 operand *right, *left, *result;
6310 symbol *tlbl, *tlbl1;
6312 /* we do it the hard way put the shift count in b
6313 and loop thru preserving the sign */
6315 right = IC_RIGHT (ic);
6316 left = IC_LEFT (ic);
6317 result = IC_RESULT (ic);
6319 aopOp (right, ic, FALSE);
6322 if (AOP_TYPE (right) == AOP_LIT)
6324 genRightShiftLiteral (left, right, result, ic, 1);
6327 /* shift count is unknown then we have to form
6328 a loop get the loop count in B : Note: we take
6329 only the lower order byte since shifting
6330 more that 32 bits make no sense anyway, ( the
6331 largest size of an object can be only 32 bits ) */
6333 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6334 emitcode ("inc", "b");
6335 freeAsmop (right, NULL, ic, TRUE);
6336 aopOp (left, ic, FALSE);
6337 aopOp (result, ic, FALSE);
6339 /* now move the left to the result if they are not the
6341 if (!sameRegs (AOP (left), AOP (result)) &&
6342 AOP_SIZE (result) > 1)
6345 size = AOP_SIZE (result);
6349 l = aopGet (AOP (left), offset, FALSE, TRUE);
6350 if (*l == '@' && IS_AOP_PREG (result))
6353 emitcode ("mov", "a,%s", l);
6354 aopPut (AOP (result), "a", offset);
6357 aopPut (AOP (result), l, offset);
6362 /* mov the highest order bit to OVR */
6363 tlbl = newiTempLabel (NULL);
6364 tlbl1 = newiTempLabel (NULL);
6366 size = AOP_SIZE (result);
6368 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6369 emitcode ("rlc", "a");
6370 emitcode ("mov", "ov,c");
6371 /* if it is only one byte then */
6374 l = aopGet (AOP (left), 0, FALSE, FALSE);
6376 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6377 emitcode ("", "%05d$:", tlbl->key + 100);
6378 emitcode ("mov", "c,ov");
6379 emitcode ("rrc", "a");
6380 emitcode ("", "%05d$:", tlbl1->key + 100);
6381 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6382 aopPut (AOP (result), "a", 0);
6386 reAdjustPreg (AOP (result));
6387 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6388 emitcode ("", "%05d$:", tlbl->key + 100);
6389 emitcode ("mov", "c,ov");
6392 l = aopGet (AOP (result), offset, FALSE, FALSE);
6394 emitcode ("rrc", "a");
6395 aopPut (AOP (result), "a", offset--);
6397 reAdjustPreg (AOP (result));
6398 emitcode ("", "%05d$:", tlbl1->key + 100);
6399 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6402 freeAsmop (left, NULL, ic, TRUE);
6403 freeAsmop (result, NULL, ic, TRUE);
6406 /*-----------------------------------------------------------------*/
6407 /* genRightShift - generate code for right shifting */
6408 /*-----------------------------------------------------------------*/
6410 genRightShift (iCode * ic)
6412 operand *right, *left, *result;
6416 symbol *tlbl, *tlbl1;
6418 /* if signed then we do it the hard way preserve the
6419 sign bit moving it inwards */
6420 retype = getSpec (operandType (IC_RESULT (ic)));
6422 if (!SPEC_USIGN (retype))
6424 genSignedRightShift (ic);
6428 /* signed & unsigned types are treated the same : i.e. the
6429 signed is NOT propagated inwards : quoting from the
6430 ANSI - standard : "for E1 >> E2, is equivalent to division
6431 by 2**E2 if unsigned or if it has a non-negative value,
6432 otherwise the result is implementation defined ", MY definition
6433 is that the sign does not get propagated */
6435 right = IC_RIGHT (ic);
6436 left = IC_LEFT (ic);
6437 result = IC_RESULT (ic);
6439 aopOp (right, ic, FALSE);
6441 /* if the shift count is known then do it
6442 as efficiently as possible */
6443 if (AOP_TYPE (right) == AOP_LIT)
6445 genRightShiftLiteral (left, right, result, ic, 0);
6449 /* shift count is unknown then we have to form
6450 a loop get the loop count in B : Note: we take
6451 only the lower order byte since shifting
6452 more that 32 bits make no sense anyway, ( the
6453 largest size of an object can be only 32 bits ) */
6455 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6456 emitcode ("inc", "b");
6457 freeAsmop (right, NULL, ic, TRUE);
6458 aopOp (left, ic, FALSE);
6459 aopOp (result, ic, FALSE);
6461 /* now move the left to the result if they are not the
6463 if (!sameRegs (AOP (left), AOP (result)) &&
6464 AOP_SIZE (result) > 1)
6467 size = AOP_SIZE (result);
6471 l = aopGet (AOP (left), offset, FALSE, TRUE);
6472 if (*l == '@' && IS_AOP_PREG (result))
6475 emitcode ("mov", "a,%s", l);
6476 aopPut (AOP (result), "a", offset);
6479 aopPut (AOP (result), l, offset);
6484 tlbl = newiTempLabel (NULL);
6485 tlbl1 = newiTempLabel (NULL);
6486 size = AOP_SIZE (result);
6489 /* if it is only one byte then */
6492 l = aopGet (AOP (left), 0, FALSE, FALSE);
6494 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6495 emitcode ("", "%05d$:", tlbl->key + 100);
6497 emitcode ("rrc", "a");
6498 emitcode ("", "%05d$:", tlbl1->key + 100);
6499 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6500 aopPut (AOP (result), "a", 0);
6504 reAdjustPreg (AOP (result));
6505 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6506 emitcode ("", "%05d$:", tlbl->key + 100);
6510 l = aopGet (AOP (result), offset, FALSE, FALSE);
6512 emitcode ("rrc", "a");
6513 aopPut (AOP (result), "a", offset--);
6515 reAdjustPreg (AOP (result));
6517 emitcode ("", "%05d$:", tlbl1->key + 100);
6518 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6521 freeAsmop (left, NULL, ic, TRUE);
6522 freeAsmop (result, NULL, ic, TRUE);
6525 /*-----------------------------------------------------------------*/
6526 /* genUnpackBits - generates code for unpacking bits */
6527 /*-----------------------------------------------------------------*/
6529 genUnpackBits (operand * result, char *rname, int ptype)
6537 etype = getSpec (operandType (result));
6538 rsize = getSize (operandType (result));
6539 /* read the first byte */
6545 emitcode ("mov", "a,@%s", rname);
6549 emitcode ("movx", "a,@%s", rname);
6553 emitcode ("movx", "a,@dptr");
6557 emitcode ("clr", "a");
6558 emitcode ("movc", "a,%s", "@a+dptr");
6562 emitcode ("lcall", "__gptrget");
6566 rlen = SPEC_BLEN (etype);
6568 /* if we have bitdisplacement then it fits */
6569 /* into this byte completely or if length is */
6570 /* less than a byte */
6571 if ((shCnt = SPEC_BSTR (etype)) ||
6572 (SPEC_BLEN (etype) <= 8))
6575 /* shift right acc */
6578 emitcode ("anl", "a,#0x%02x",
6579 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6580 aopPut (AOP (result), "a", offset++);
6584 /* bit field did not fit in a byte */
6585 aopPut (AOP (result), "a", offset++);
6594 emitcode ("inc", "%s", rname);
6595 emitcode ("mov", "a,@%s", rname);
6599 emitcode ("inc", "%s", rname);
6600 emitcode ("movx", "a,@%s", rname);
6604 emitcode ("inc", "dptr");
6605 emitcode ("movx", "a,@dptr");
6609 emitcode ("clr", "a");
6610 emitcode ("inc", "dptr");
6611 emitcode ("movc", "a", "@a+dptr");
6615 emitcode ("inc", "dptr");
6616 emitcode ("lcall", "__gptrget");
6621 /* if we are done */
6625 aopPut (AOP (result), "a", offset++);
6631 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6633 aopPut (AOP (result), "a", offset++);
6641 aopPut (AOP (result), zero, offset++);
6647 /*-----------------------------------------------------------------*/
6648 /* genDataPointerGet - generates code when ptr offset is known */
6649 /*-----------------------------------------------------------------*/
6651 genDataPointerGet (operand * left,
6657 int size, offset = 0;
6658 aopOp (result, ic, TRUE);
6660 /* get the string representation of the name */
6661 l = aopGet (AOP (left), 0, FALSE, TRUE);
6662 size = AOP_SIZE (result);
6666 sprintf (buffer, "(%s + %d)", l + 1, offset);
6668 sprintf (buffer, "%s", l + 1);
6669 aopPut (AOP (result), buffer, offset++);
6672 freeAsmop (left, NULL, ic, TRUE);
6673 freeAsmop (result, NULL, ic, TRUE);
6676 /*-----------------------------------------------------------------*/
6677 /* genNearPointerGet - emitcode for near pointer fetch */
6678 /*-----------------------------------------------------------------*/
6680 genNearPointerGet (operand * left,
6688 sym_link *rtype, *retype;
6689 sym_link *ltype = operandType (left);
6692 rtype = operandType (result);
6693 retype = getSpec (rtype);
6695 aopOp (left, ic, FALSE);
6697 /* if left is rematerialisable and
6698 result is not bit variable type and
6699 the left is pointer to data space i.e
6700 lower 128 bytes of space */
6701 if (AOP_TYPE (left) == AOP_IMMD &&
6702 !IS_BITVAR (retype) &&
6703 DCL_TYPE (ltype) == POINTER)
6705 genDataPointerGet (left, result, ic);
6709 /* if the value is already in a pointer register
6710 then don't need anything more */
6711 if (!AOP_INPREG (AOP (left)))
6713 /* otherwise get a free pointer register */
6715 preg = getFreePtr (ic, &aop, FALSE);
6716 emitcode ("mov", "%s,%s",
6718 aopGet (AOP (left), 0, FALSE, TRUE));
6722 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6724 aopOp (result, ic, FALSE);
6726 /* if bitfield then unpack the bits */
6727 if (IS_BITVAR (retype))
6728 genUnpackBits (result, rname, POINTER);
6731 /* we have can just get the values */
6732 int size = AOP_SIZE (result);
6737 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6740 emitcode ("mov", "a,@%s", rname);
6741 aopPut (AOP (result), "a", offset);
6745 sprintf (buffer, "@%s", rname);
6746 aopPut (AOP (result), buffer, offset);
6750 emitcode ("inc", "%s", rname);
6754 /* now some housekeeping stuff */
6755 if (aop) /* we had to allocate for this iCode */
6757 if (pi) { /* post increment present */
6758 aopPut(AOP ( left ),rname,0);
6760 freeAsmop (NULL, aop, ic, TRUE);
6764 /* we did not allocate which means left
6765 already in a pointer register, then
6766 if size > 0 && this could be used again
6767 we have to point it back to where it
6769 if ((AOP_SIZE (result) > 1 &&
6770 !OP_SYMBOL (left)->remat &&
6771 (OP_SYMBOL (left)->liveTo > ic->seq ||
6775 int size = AOP_SIZE (result) - 1;
6777 emitcode ("dec", "%s", rname);
6782 freeAsmop (left, NULL, ic, TRUE);
6783 freeAsmop (result, NULL, ic, TRUE);
6784 if (pi) pi->generated = 1;
6787 /*-----------------------------------------------------------------*/
6788 /* genPagedPointerGet - emitcode for paged pointer fetch */
6789 /*-----------------------------------------------------------------*/
6791 genPagedPointerGet (operand * left,
6799 sym_link *rtype, *retype;
6801 rtype = operandType (result);
6802 retype = getSpec (rtype);
6804 aopOp (left, ic, FALSE);
6806 /* if the value is already in a pointer register
6807 then don't need anything more */
6808 if (!AOP_INPREG (AOP (left)))
6810 /* otherwise get a free pointer register */
6812 preg = getFreePtr (ic, &aop, FALSE);
6813 emitcode ("mov", "%s,%s",
6815 aopGet (AOP (left), 0, FALSE, TRUE));
6819 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6821 aopOp (result, ic, FALSE);
6823 /* if bitfield then unpack the bits */
6824 if (IS_BITVAR (retype))
6825 genUnpackBits (result, rname, PPOINTER);
6828 /* we have can just get the values */
6829 int size = AOP_SIZE (result);
6835 emitcode ("movx", "a,@%s", rname);
6836 aopPut (AOP (result), "a", offset);
6841 emitcode ("inc", "%s", rname);
6845 /* now some housekeeping stuff */
6846 if (aop) /* we had to allocate for this iCode */
6848 if (pi) aopPut ( AOP (left), rname, 0);
6849 freeAsmop (NULL, aop, ic, TRUE);
6853 /* we did not allocate which means left
6854 already in a pointer register, then
6855 if size > 0 && this could be used again
6856 we have to point it back to where it
6858 if ((AOP_SIZE (result) > 1 &&
6859 !OP_SYMBOL (left)->remat &&
6860 (OP_SYMBOL (left)->liveTo > ic->seq ||
6864 int size = AOP_SIZE (result) - 1;
6866 emitcode ("dec", "%s", rname);
6871 freeAsmop (left, NULL, ic, TRUE);
6872 freeAsmop (result, NULL, ic, TRUE);
6873 if (pi) pi->generated = 1;
6877 /*-----------------------------------------------------------------*/
6878 /* genFarPointerGet - gget value from far space */
6879 /*-----------------------------------------------------------------*/
6881 genFarPointerGet (operand * left,
6882 operand * result, iCode * ic, iCode * pi)
6885 sym_link *retype = getSpec (operandType (result));
6887 aopOp (left, ic, FALSE);
6889 /* if the operand is already in dptr
6890 then we do nothing else we move the value to dptr */
6891 if (AOP_TYPE (left) != AOP_STR)
6893 /* if this is remateriazable */
6894 if (AOP_TYPE (left) == AOP_IMMD)
6895 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6897 { /* we need to get it byte by byte */
6898 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6899 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6902 /* so dptr know contains the address */
6903 aopOp (result, ic, FALSE);
6905 /* if bit then unpack */
6906 if (IS_BITVAR (retype))
6907 genUnpackBits (result, "dptr", FPOINTER);
6910 size = AOP_SIZE (result);
6915 emitcode ("movx", "a,@dptr");
6916 aopPut (AOP (result), "a", offset++);
6918 emitcode ("inc", "dptr");
6922 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6923 aopPut ( AOP (left), "dpl", 0);
6924 aopPut ( AOP (left), "dph", 1);
6927 freeAsmop (left, NULL, ic, TRUE);
6928 freeAsmop (result, NULL, ic, TRUE);
6931 /*-----------------------------------------------------------------*/
6932 /* genCodePointerGet - gget value from code space */
6933 /*-----------------------------------------------------------------*/
6935 genCodePointerGet (operand * left,
6936 operand * result, iCode * ic, iCode *pi)
6939 sym_link *retype = getSpec (operandType (result));
6941 aopOp (left, ic, FALSE);
6943 /* if the operand is already in dptr
6944 then we do nothing else we move the value to dptr */
6945 if (AOP_TYPE (left) != AOP_STR)
6947 /* if this is remateriazable */
6948 if (AOP_TYPE (left) == AOP_IMMD)
6949 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6951 { /* we need to get it byte by byte */
6952 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6953 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6956 /* so dptr know contains the address */
6957 aopOp (result, ic, FALSE);
6959 /* if bit then unpack */
6960 if (IS_BITVAR (retype))
6961 genUnpackBits (result, "dptr", CPOINTER);
6964 size = AOP_SIZE (result);
6969 emitcode ("clr", "a");
6970 emitcode ("movc", "a,@a+dptr");
6971 aopPut (AOP (result), "a", offset++);
6973 emitcode ("inc", "dptr");
6977 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6978 aopPut ( AOP (left), "dpl", 0);
6979 aopPut ( AOP (left), "dph", 1);
6982 freeAsmop (left, NULL, ic, TRUE);
6983 freeAsmop (result, NULL, ic, TRUE);
6986 /*-----------------------------------------------------------------*/
6987 /* genGenPointerGet - gget value from generic pointer space */
6988 /*-----------------------------------------------------------------*/
6990 genGenPointerGet (operand * left,
6991 operand * result, iCode * ic, iCode *pi)
6994 sym_link *retype = getSpec (operandType (result));
6996 aopOp (left, ic, FALSE);
6998 /* if the operand is already in dptr
6999 then we do nothing else we move the value to dptr */
7000 if (AOP_TYPE (left) != AOP_STR)
7002 /* if this is remateriazable */
7003 if (AOP_TYPE (left) == AOP_IMMD)
7005 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7006 emitcode ("mov", "b,#%d", pointerCode (retype));
7009 { /* we need to get it byte by byte */
7010 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7011 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7012 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7015 /* so dptr know contains the address */
7016 aopOp (result, ic, FALSE);
7018 /* if bit then unpack */
7019 if (IS_BITVAR (retype))
7020 genUnpackBits (result, "dptr", GPOINTER);
7023 size = AOP_SIZE (result);
7028 emitcode ("lcall", "__gptrget");
7029 aopPut (AOP (result), "a", offset++);
7031 emitcode ("inc", "dptr");
7035 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7036 aopPut ( AOP (left), "dpl", 0);
7037 aopPut ( AOP (left), "dph", 1);
7040 freeAsmop (left, NULL, ic, TRUE);
7041 freeAsmop (result, NULL, ic, TRUE);
7044 /*-----------------------------------------------------------------*/
7045 /* genPointerGet - generate code for pointer get */
7046 /*-----------------------------------------------------------------*/
7048 genPointerGet (iCode * ic, iCode *pi)
7050 operand *left, *result;
7051 sym_link *type, *etype;
7054 left = IC_LEFT (ic);
7055 result = IC_RESULT (ic);
7057 /* depending on the type of pointer we need to
7058 move it to the correct pointer register */
7059 type = operandType (left);
7060 etype = getSpec (type);
7061 /* if left is of type of pointer then it is simple */
7062 if (IS_PTR (type) && !IS_FUNC (type->next))
7063 p_type = DCL_TYPE (type);
7066 /* we have to go by the storage class */
7067 p_type = PTR_TYPE (SPEC_OCLS (etype));
7070 /* now that we have the pointer type we assign
7071 the pointer values */
7077 genNearPointerGet (left, result, ic, pi);
7081 genPagedPointerGet (left, result, ic, pi);
7085 genFarPointerGet (left, result, ic, pi);
7089 genCodePointerGet (left, result, ic, pi);
7093 genGenPointerGet (left, result, ic, pi);
7099 /*-----------------------------------------------------------------*/
7100 /* genPackBits - generates code for packed bit storage */
7101 /*-----------------------------------------------------------------*/
7103 genPackBits (sym_link * etype,
7105 char *rname, int p_type)
7113 blen = SPEC_BLEN (etype);
7114 bstr = SPEC_BSTR (etype);
7116 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7119 /* if the bit lenth is less than or */
7120 /* it exactly fits a byte then */
7121 if (SPEC_BLEN (etype) <= 8)
7123 shCount = SPEC_BSTR (etype);
7125 /* shift left acc */
7128 if (SPEC_BLEN (etype) < 8)
7129 { /* if smaller than a byte */
7135 emitcode ("mov", "b,a");
7136 emitcode ("mov", "a,@%s", rname);
7140 emitcode ("mov", "b,a");
7141 emitcode ("movx", "a,@dptr");
7145 emitcode ("push", "b");
7146 emitcode ("push", "acc");
7147 emitcode ("lcall", "__gptrget");
7148 emitcode ("pop", "b");
7152 emitcode ("anl", "a,#0x%02x", (unsigned char)
7153 ((unsigned char) (0xFF << (blen + bstr)) |
7154 (unsigned char) (0xFF >> (8 - bstr))));
7155 emitcode ("orl", "a,b");
7156 if (p_type == GPOINTER)
7157 emitcode ("pop", "b");
7164 emitcode ("mov", "@%s,a", rname);
7168 emitcode ("movx", "@dptr,a");
7172 emitcode ("lcall", "__gptrput");
7177 if (SPEC_BLEN (etype) <= 8)
7180 emitcode ("inc", "%s", rname);
7181 rLen = SPEC_BLEN (etype);
7183 /* now generate for lengths greater than one byte */
7187 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7199 emitcode ("mov", "@%s,a", rname);
7202 emitcode ("mov", "@%s,%s", rname, l);
7207 emitcode ("movx", "@dptr,a");
7212 emitcode ("lcall", "__gptrput");
7215 emitcode ("inc", "%s", rname);
7220 /* last last was not complete */
7223 /* save the byte & read byte */
7227 emitcode ("mov", "b,a");
7228 emitcode ("mov", "a,@%s", rname);
7232 emitcode ("mov", "b,a");
7233 emitcode ("movx", "a,@dptr");
7237 emitcode ("push", "b");
7238 emitcode ("push", "acc");
7239 emitcode ("lcall", "__gptrget");
7240 emitcode ("pop", "b");
7244 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7245 emitcode ("orl", "a,b");
7248 if (p_type == GPOINTER)
7249 emitcode ("pop", "b");
7255 emitcode ("mov", "@%s,a", rname);
7259 emitcode ("movx", "@dptr,a");
7263 emitcode ("lcall", "__gptrput");
7267 /*-----------------------------------------------------------------*/
7268 /* genDataPointerSet - remat pointer to data space */
7269 /*-----------------------------------------------------------------*/
7271 genDataPointerSet (operand * right,
7275 int size, offset = 0;
7276 char *l, buffer[256];
7278 aopOp (right, ic, FALSE);
7280 l = aopGet (AOP (result), 0, FALSE, TRUE);
7281 size = AOP_SIZE (right);
7285 sprintf (buffer, "(%s + %d)", l + 1, offset);
7287 sprintf (buffer, "%s", l + 1);
7288 emitcode ("mov", "%s,%s", buffer,
7289 aopGet (AOP (right), offset++, FALSE, FALSE));
7292 freeAsmop (right, NULL, ic, TRUE);
7293 freeAsmop (result, NULL, ic, TRUE);
7296 /*-----------------------------------------------------------------*/
7297 /* genNearPointerSet - emitcode for near pointer put */
7298 /*-----------------------------------------------------------------*/
7300 genNearPointerSet (operand * right,
7308 sym_link *retype, *letype;
7309 sym_link *ptype = operandType (result);
7311 retype = getSpec (operandType (right));
7312 letype = getSpec (ptype);
7313 aopOp (result, ic, FALSE);
7315 /* if the result is rematerializable &
7316 in data space & not a bit variable */
7317 if (AOP_TYPE (result) == AOP_IMMD &&
7318 DCL_TYPE (ptype) == POINTER &&
7319 !IS_BITVAR (retype) &&
7320 !IS_BITVAR (letype))
7322 genDataPointerSet (right, result, ic);
7326 /* if the value is already in a pointer register
7327 then don't need anything more */
7328 if (!AOP_INPREG (AOP (result)))
7330 /* otherwise get a free pointer register */
7332 preg = getFreePtr (ic, &aop, FALSE);
7333 emitcode ("mov", "%s,%s",
7335 aopGet (AOP (result), 0, FALSE, TRUE));
7339 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7341 aopOp (right, ic, FALSE);
7343 /* if bitfield then unpack the bits */
7344 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7345 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7348 /* we have can just get the values */
7349 int size = AOP_SIZE (right);
7354 l = aopGet (AOP (right), offset, FALSE, TRUE);
7358 emitcode ("mov", "@%s,a", rname);
7361 emitcode ("mov", "@%s,%s", rname, l);
7363 emitcode ("inc", "%s", rname);
7368 /* now some housekeeping stuff */
7369 if (aop) /* we had to allocate for this iCode */
7371 if (pi) aopPut (AOP (result),rname,0);
7372 freeAsmop (NULL, aop, ic, TRUE);
7376 /* we did not allocate which means left
7377 already in a pointer register, then
7378 if size > 0 && this could be used again
7379 we have to point it back to where it
7381 if ((AOP_SIZE (right) > 1 &&
7382 !OP_SYMBOL (result)->remat &&
7383 (OP_SYMBOL (result)->liveTo > ic->seq ||
7387 int size = AOP_SIZE (right) - 1;
7389 emitcode ("dec", "%s", rname);
7394 if (pi) pi->generated = 1;
7395 freeAsmop (result, NULL, ic, TRUE);
7396 freeAsmop (right, NULL, ic, TRUE);
7399 /*-----------------------------------------------------------------*/
7400 /* genPagedPointerSet - emitcode for Paged pointer put */
7401 /*-----------------------------------------------------------------*/
7403 genPagedPointerSet (operand * right,
7411 sym_link *retype, *letype;
7413 retype = getSpec (operandType (right));
7414 letype = getSpec (operandType (result));
7416 aopOp (result, ic, FALSE);
7418 /* if the value is already in a pointer register
7419 then don't need anything more */
7420 if (!AOP_INPREG (AOP (result)))
7422 /* otherwise get a free pointer register */
7424 preg = getFreePtr (ic, &aop, FALSE);
7425 emitcode ("mov", "%s,%s",
7427 aopGet (AOP (result), 0, FALSE, TRUE));
7431 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7433 aopOp (right, ic, FALSE);
7435 /* if bitfield then unpack the bits */
7436 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7437 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7440 /* we have can just get the values */
7441 int size = AOP_SIZE (right);
7446 l = aopGet (AOP (right), offset, FALSE, TRUE);
7449 emitcode ("movx", "@%s,a", rname);
7452 emitcode ("inc", "%s", rname);
7458 /* now some housekeeping stuff */
7459 if (aop) /* we had to allocate for this iCode */
7461 if (pi) aopPut (AOP (result),rname,0);
7462 freeAsmop (NULL, aop, ic, TRUE);
7466 /* we did not allocate which means left
7467 already in a pointer register, then
7468 if size > 0 && this could be used again
7469 we have to point it back to where it
7471 if (AOP_SIZE (right) > 1 &&
7472 !OP_SYMBOL (result)->remat &&
7473 (OP_SYMBOL (result)->liveTo > ic->seq ||
7476 int size = AOP_SIZE (right) - 1;
7478 emitcode ("dec", "%s", rname);
7483 if (pi) pi->generated = 1;
7484 freeAsmop (result, NULL, ic, TRUE);
7485 freeAsmop (right, NULL, ic, TRUE);
7490 /*-----------------------------------------------------------------*/
7491 /* genFarPointerSet - set value from far space */
7492 /*-----------------------------------------------------------------*/
7494 genFarPointerSet (operand * right,
7495 operand * result, iCode * ic, iCode * pi)
7498 sym_link *retype = getSpec (operandType (right));
7499 sym_link *letype = getSpec (operandType (result));
7500 aopOp (result, ic, FALSE);
7502 /* if the operand is already in dptr
7503 then we do nothing else we move the value to dptr */
7504 if (AOP_TYPE (result) != AOP_STR)
7506 /* if this is remateriazable */
7507 if (AOP_TYPE (result) == AOP_IMMD)
7508 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7510 { /* we need to get it byte by byte */
7511 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7512 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7515 /* so dptr know contains the address */
7516 aopOp (right, ic, FALSE);
7518 /* if bit then unpack */
7519 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7520 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7523 size = AOP_SIZE (right);
7528 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7530 emitcode ("movx", "@dptr,a");
7532 emitcode ("inc", "dptr");
7535 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7536 aopPut (AOP(result),"dpl",0);
7537 aopPut (AOP(result),"dph",1);
7540 freeAsmop (result, NULL, ic, TRUE);
7541 freeAsmop (right, NULL, ic, TRUE);
7544 /*-----------------------------------------------------------------*/
7545 /* genGenPointerSet - set value from generic pointer space */
7546 /*-----------------------------------------------------------------*/
7548 genGenPointerSet (operand * right,
7549 operand * result, iCode * ic, iCode * pi)
7552 sym_link *retype = getSpec (operandType (right));
7553 sym_link *letype = getSpec (operandType (result));
7555 aopOp (result, ic, FALSE);
7557 /* if the operand is already in dptr
7558 then we do nothing else we move the value to dptr */
7559 if (AOP_TYPE (result) != AOP_STR)
7561 /* if this is remateriazable */
7562 if (AOP_TYPE (result) == AOP_IMMD)
7564 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7565 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7568 { /* we need to get it byte by byte */
7569 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7570 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7571 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7574 /* so dptr know contains the address */
7575 aopOp (right, ic, FALSE);
7577 /* if bit then unpack */
7578 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7579 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7582 size = AOP_SIZE (right);
7587 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7589 emitcode ("lcall", "__gptrput");
7591 emitcode ("inc", "dptr");
7595 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7596 aopPut (AOP(result),"dpl",0);
7597 aopPut (AOP(result),"dph",1);
7600 freeAsmop (result, NULL, ic, TRUE);
7601 freeAsmop (right, NULL, ic, TRUE);
7604 /*-----------------------------------------------------------------*/
7605 /* genPointerSet - stores the value into a pointer location */
7606 /*-----------------------------------------------------------------*/
7608 genPointerSet (iCode * ic, iCode *pi)
7610 operand *right, *result;
7611 sym_link *type, *etype;
7614 right = IC_RIGHT (ic);
7615 result = IC_RESULT (ic);
7617 /* depending on the type of pointer we need to
7618 move it to the correct pointer register */
7619 type = operandType (result);
7620 etype = getSpec (type);
7621 /* if left is of type of pointer then it is simple */
7622 if (IS_PTR (type) && !IS_FUNC (type->next))
7624 p_type = DCL_TYPE (type);
7628 /* we have to go by the storage class */
7629 p_type = PTR_TYPE (SPEC_OCLS (etype));
7632 /* now that we have the pointer type we assign
7633 the pointer values */
7639 genNearPointerSet (right, result, ic, pi);
7643 genPagedPointerSet (right, result, ic, pi);
7647 genFarPointerSet (right, result, ic, pi);
7651 genGenPointerSet (right, result, ic, pi);
7657 /*-----------------------------------------------------------------*/
7658 /* genIfx - generate code for Ifx statement */
7659 /*-----------------------------------------------------------------*/
7661 genIfx (iCode * ic, iCode * popIc)
7663 operand *cond = IC_COND (ic);
7666 aopOp (cond, ic, FALSE);
7668 /* get the value into acc */
7669 if (AOP_TYPE (cond) != AOP_CRY)
7673 /* the result is now in the accumulator */
7674 freeAsmop (cond, NULL, ic, TRUE);
7676 /* if there was something to be popped then do it */
7680 /* if the condition is a bit variable */
7681 if (isbit && IS_ITEMP (cond) &&
7683 genIfxJump (ic, SPIL_LOC (cond)->rname);
7684 else if (isbit && !IS_ITEMP (cond))
7685 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7687 genIfxJump (ic, "a");
7692 /*-----------------------------------------------------------------*/
7693 /* genAddrOf - generates code for address of */
7694 /*-----------------------------------------------------------------*/
7696 genAddrOf (iCode * ic)
7698 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7701 aopOp (IC_RESULT (ic), ic, FALSE);
7703 /* if the operand is on the stack then we
7704 need to get the stack offset of this
7708 /* if it has an offset then we need to compute
7712 emitcode ("mov", "a,_bp");
7713 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7714 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7718 /* we can just move _bp */
7719 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7721 /* fill the result with zero */
7722 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7727 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7733 /* object not on stack then we need the name */
7734 size = AOP_SIZE (IC_RESULT (ic));
7739 char s[SDCC_NAME_MAX];
7741 sprintf (s, "#(%s >> %d)",
7745 sprintf (s, "#%s", sym->rname);
7746 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7754 /*-----------------------------------------------------------------*/
7755 /* genFarFarAssign - assignment when both are in far space */
7756 /*-----------------------------------------------------------------*/
7758 genFarFarAssign (operand * result, operand * right, iCode * ic)
7760 int size = AOP_SIZE (right);
7763 /* first push the right side on to the stack */
7766 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7768 emitcode ("push", "acc");
7771 freeAsmop (right, NULL, ic, FALSE);
7772 /* now assign DPTR to result */
7773 aopOp (result, ic, FALSE);
7774 size = AOP_SIZE (result);
7777 emitcode ("pop", "acc");
7778 aopPut (AOP (result), "a", --offset);
7780 freeAsmop (result, NULL, ic, FALSE);
7784 /*-----------------------------------------------------------------*/
7785 /* genAssign - generate code for assignment */
7786 /*-----------------------------------------------------------------*/
7788 genAssign (iCode * ic)
7790 operand *result, *right;
7792 unsigned long lit = 0L;
7794 result = IC_RESULT (ic);
7795 right = IC_RIGHT (ic);
7797 /* if they are the same */
7798 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7801 aopOp (right, ic, FALSE);
7803 /* special case both in far space */
7804 if (AOP_TYPE (right) == AOP_DPTR &&
7805 IS_TRUE_SYMOP (result) &&
7806 isOperandInFarSpace (result))
7809 genFarFarAssign (result, right, ic);
7813 aopOp (result, ic, TRUE);
7815 /* if they are the same registers */
7816 if (sameRegs (AOP (right), AOP (result)))
7819 /* if the result is a bit */
7820 if (AOP_TYPE (result) == AOP_CRY)
7823 /* if the right size is a literal then
7824 we know what the value is */
7825 if (AOP_TYPE (right) == AOP_LIT)
7827 if (((int) operandLitValue (right)))
7828 aopPut (AOP (result), one, 0);
7830 aopPut (AOP (result), zero, 0);
7834 /* the right is also a bit variable */
7835 if (AOP_TYPE (right) == AOP_CRY)
7837 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7838 aopPut (AOP (result), "c", 0);
7844 aopPut (AOP (result), "a", 0);
7848 /* bit variables done */
7850 size = AOP_SIZE (result);
7852 if (AOP_TYPE (right) == AOP_LIT)
7853 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7855 (AOP_TYPE (result) != AOP_REG) &&
7856 (AOP_TYPE (right) == AOP_LIT) &&
7857 !IS_FLOAT (operandType (right)) &&
7860 emitcode ("clr", "a");
7863 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7864 aopPut (AOP (result), "a", size);
7866 aopPut (AOP (result),
7867 aopGet (AOP (right), size, FALSE, FALSE),
7875 aopPut (AOP (result),
7876 aopGet (AOP (right), offset, FALSE, FALSE),
7883 freeAsmop (right, NULL, ic, TRUE);
7884 freeAsmop (result, NULL, ic, TRUE);
7887 /*-----------------------------------------------------------------*/
7888 /* genJumpTab - genrates code for jump table */
7889 /*-----------------------------------------------------------------*/
7891 genJumpTab (iCode * ic)
7896 aopOp (IC_JTCOND (ic), ic, FALSE);
7897 /* get the condition into accumulator */
7898 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7900 /* multiply by three */
7901 emitcode ("add", "a,acc");
7902 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7903 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7905 jtab = newiTempLabel (NULL);
7906 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7907 emitcode ("jmp", "@a+dptr");
7908 emitcode ("", "%05d$:", jtab->key + 100);
7909 /* now generate the jump labels */
7910 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7911 jtab = setNextItem (IC_JTLABELS (ic)))
7912 emitcode ("ljmp", "%05d$", jtab->key + 100);
7916 /*-----------------------------------------------------------------*/
7917 /* genCast - gen code for casting */
7918 /*-----------------------------------------------------------------*/
7920 genCast (iCode * ic)
7922 operand *result = IC_RESULT (ic);
7923 sym_link *ctype = operandType (IC_LEFT (ic));
7924 sym_link *rtype = operandType (IC_RIGHT (ic));
7925 operand *right = IC_RIGHT (ic);
7928 /* if they are equivalent then do nothing */
7929 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7932 aopOp (right, ic, FALSE);
7933 aopOp (result, ic, FALSE);
7935 /* if the result is a bit */
7936 if (AOP_TYPE (result) == AOP_CRY)
7938 /* if the right size is a literal then
7939 we know what the value is */
7940 if (AOP_TYPE (right) == AOP_LIT)
7942 if (((int) operandLitValue (right)))
7943 aopPut (AOP (result), one, 0);
7945 aopPut (AOP (result), zero, 0);
7950 /* the right is also a bit variable */
7951 if (AOP_TYPE (right) == AOP_CRY)
7953 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7954 aopPut (AOP (result), "c", 0);
7960 aopPut (AOP (result), "a", 0);
7964 /* if they are the same size : or less */
7965 if (AOP_SIZE (result) <= AOP_SIZE (right))
7968 /* if they are in the same place */
7969 if (sameRegs (AOP (right), AOP (result)))
7972 /* if they in different places then copy */
7973 size = AOP_SIZE (result);
7977 aopPut (AOP (result),
7978 aopGet (AOP (right), offset, FALSE, FALSE),
7986 /* if the result is of type pointer */
7991 sym_link *type = operandType (right);
7992 sym_link *etype = getSpec (type);
7994 /* pointer to generic pointer */
7995 if (IS_GENPTR (ctype))
8000 p_type = DCL_TYPE (type);
8003 /* we have to go by the storage class */
8004 p_type = PTR_TYPE (SPEC_OCLS (etype));
8007 /* the first two bytes are known */
8008 size = GPTRSIZE - 1;
8012 aopPut (AOP (result),
8013 aopGet (AOP (right), offset, FALSE, FALSE),
8017 /* the last byte depending on type */
8035 /* this should never happen */
8036 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8037 "got unknown pointer type");
8040 aopPut (AOP (result), l, GPTRSIZE - 1);
8044 /* just copy the pointers */
8045 size = AOP_SIZE (result);
8049 aopPut (AOP (result),
8050 aopGet (AOP (right), offset, FALSE, FALSE),
8057 /* so we now know that the size of destination is greater
8058 than the size of the source */
8059 /* we move to result for the size of source */
8060 size = AOP_SIZE (right);
8064 aopPut (AOP (result),
8065 aopGet (AOP (right), offset, FALSE, FALSE),
8070 /* now depending on the sign of the source && destination */
8071 size = AOP_SIZE (result) - AOP_SIZE (right);
8072 /* if unsigned or not an integral type */
8073 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8076 aopPut (AOP (result), zero, offset++);
8080 /* we need to extend the sign :{ */
8081 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8084 emitcode ("rlc", "a");
8085 emitcode ("subb", "a,acc");
8087 aopPut (AOP (result), "a", offset++);
8090 /* we are done hurray !!!! */
8093 freeAsmop (right, NULL, ic, TRUE);
8094 freeAsmop (result, NULL, ic, TRUE);
8098 /*-----------------------------------------------------------------*/
8099 /* genDjnz - generate decrement & jump if not zero instrucion */
8100 /*-----------------------------------------------------------------*/
8102 genDjnz (iCode * ic, iCode * ifx)
8108 /* if the if condition has a false label
8109 then we cannot save */
8113 /* if the minus is not of the form
8115 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8116 !IS_OP_LITERAL (IC_RIGHT (ic)))
8119 if (operandLitValue (IC_RIGHT (ic)) != 1)
8122 /* if the size of this greater than one then no
8124 if (getSize (operandType (IC_RESULT (ic))) > 1)
8127 /* otherwise we can save BIG */
8128 lbl = newiTempLabel (NULL);
8129 lbl1 = newiTempLabel (NULL);
8131 aopOp (IC_RESULT (ic), ic, FALSE);
8133 if (AOP_NEEDSACC(IC_RESULT(ic)))
8135 /* If the result is accessed indirectly via
8136 * the accumulator, we must explicitly write
8137 * it back after the decrement.
8139 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8141 if (strcmp(rByte, "a"))
8143 /* Something is hopelessly wrong */
8144 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8145 __FILE__, __LINE__);
8146 /* We can just give up; the generated code will be inefficient,
8149 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8152 emitcode ("dec", "%s", rByte);
8153 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8154 emitcode ("jnz", "%05d$", lbl->key + 100);
8156 else if (IS_AOP_PREG (IC_RESULT (ic)))
8158 emitcode ("dec", "%s",
8159 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8160 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8161 emitcode ("jnz", "%05d$", lbl->key + 100);
8165 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8168 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8169 emitcode ("", "%05d$:", lbl->key + 100);
8170 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8171 emitcode ("", "%05d$:", lbl1->key + 100);
8173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8178 /*-----------------------------------------------------------------*/
8179 /* genReceive - generate code for a receive iCode */
8180 /*-----------------------------------------------------------------*/
8182 genReceive (iCode * ic)
8184 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8185 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8186 IS_TRUE_SYMOP (IC_RESULT (ic))))
8189 int size = getSize (operandType (IC_RESULT (ic)));
8190 int offset = fReturnSizeMCS51 - size;
8193 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8194 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8197 aopOp (IC_RESULT (ic), ic, FALSE);
8198 size = AOP_SIZE (IC_RESULT (ic));
8202 emitcode ("pop", "acc");
8203 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8210 aopOp (IC_RESULT (ic), ic, FALSE);
8212 assignResultValue (IC_RESULT (ic));
8215 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8218 /*-----------------------------------------------------------------*/
8219 /* gen51Code - generate code for 8051 based controllers */
8220 /*-----------------------------------------------------------------*/
8222 gen51Code (iCode * lic)
8227 lineHead = lineCurr = NULL;
8229 /* print the allocation information */
8231 printAllocInfo (currFunc, codeOutFile);
8232 /* if debug information required */
8233 /* if (options.debug && currFunc) { */
8236 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8238 if (IS_STATIC (currFunc->etype))
8239 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8241 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8244 /* stack pointer name */
8245 if (options.useXstack)
8251 for (ic = lic; ic; ic = ic->next)
8254 if (cln != ic->lineno)
8259 emitcode ("", "C$%s$%d$%d$%d ==.",
8260 FileBaseName (ic->filename), ic->lineno,
8261 ic->level, ic->block);
8264 emitcode (";", "%s %d", ic->filename, ic->lineno);
8267 /* if the result is marked as
8268 spilt and rematerializable or code for
8269 this has already been generated then
8271 if (resultRemat (ic) || ic->generated)
8274 /* depending on the operation */
8294 /* IPOP happens only when trying to restore a
8295 spilt live range, if there is an ifx statement
8296 following this pop then the if statement might
8297 be using some of the registers being popped which
8298 would destory the contents of the register so
8299 we need to check for this condition and handle it */
8301 ic->next->op == IFX &&
8302 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8303 genIfx (ic->next, ic);
8321 genEndFunction (ic);
8341 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8358 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8362 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8369 /* note these two are xlated by algebraic equivalence
8370 during parsing SDCC.y */
8371 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8372 "got '>=' or '<=' shouldn't have come here");
8376 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8388 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8392 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8396 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8423 case GET_VALUE_AT_ADDRESS:
8424 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8428 if (POINTER_SET (ic))
8429 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8455 addSet (&_G.sendSet, ic);
8464 /* now we are ready to call the
8465 peep hole optimizer */
8466 if (!options.nopeep)
8467 peepHole (&lineHead);
8469 /* now do the actual printing */
8470 printLine (lineHead, codeOutFile);