1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[MAX_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1451 /* find the registers in use at this time
1452 and push them away to safety */
1453 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1457 if (options.useXstack)
1459 if (bitVectBitValue (rsave, R0_IDX))
1460 emitcode ("mov", "b,r0");
1461 emitcode ("mov", "r0,%s", spname);
1462 for (i = 0; i < mcs51_nRegs; i++)
1464 if (bitVectBitValue (rsave, i))
1467 emitcode ("mov", "a,b");
1469 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1470 emitcode ("movx", "@r0,a");
1471 emitcode ("inc", "r0");
1474 emitcode ("mov", "%s,r0", spname);
1475 if (bitVectBitValue (rsave, R0_IDX))
1476 emitcode ("mov", "r0,b");
1479 for (i = 0; i < mcs51_nRegs; i++)
1481 if (bitVectBitValue (rsave, i))
1482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1485 detype = getSpec (operandType (IC_LEFT (ic)));
1487 #if 0 // why should we do this here??? jwk20011105
1489 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1490 IS_ISR (currFunc->etype) &&
1492 saveRBank (SPEC_BANK (detype), ic, TRUE);
1496 /*-----------------------------------------------------------------*/
1497 /* unsaveRegisters - pop the pushed registers */
1498 /*-----------------------------------------------------------------*/
1500 unsaveRegisters (iCode * ic)
1504 /* find the registers in use at this time
1505 and push them away to safety */
1506 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1509 if (options.useXstack)
1511 emitcode ("mov", "r0,%s", spname);
1512 for (i = mcs51_nRegs; i >= 0; i--)
1514 if (bitVectBitValue (rsave, i))
1516 emitcode ("dec", "r0");
1517 emitcode ("movx", "a,@r0");
1519 emitcode ("mov", "b,a");
1521 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = mcs51_nRegs; i >= 0; i--)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1539 /*-----------------------------------------------------------------*/
1541 /*-----------------------------------------------------------------*/
1543 pushSide (operand * oper, int size)
1548 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1549 if (AOP_TYPE (oper) != AOP_REG &&
1550 AOP_TYPE (oper) != AOP_DIR &&
1553 emitcode ("mov", "a,%s", l);
1554 emitcode ("push", "acc");
1557 emitcode ("push", "%s", l);
1561 /*-----------------------------------------------------------------*/
1562 /* assignResultValue - */
1563 /*-----------------------------------------------------------------*/
1565 assignResultValue (operand * oper)
1568 int size = AOP_SIZE (oper);
1571 aopPut (AOP (oper), fReturn[offset], offset);
1577 /*-----------------------------------------------------------------*/
1578 /* genXpush - pushes onto the external stack */
1579 /*-----------------------------------------------------------------*/
1581 genXpush (iCode * ic)
1583 asmop *aop = newAsmop (0);
1585 int size, offset = 0;
1587 aopOp (IC_LEFT (ic), ic, FALSE);
1588 r = getFreePtr (ic, &aop, FALSE);
1591 emitcode ("mov", "%s,_spx", r->name);
1593 size = AOP_SIZE (IC_LEFT (ic));
1597 char *l = aopGet (AOP (IC_LEFT (ic)),
1598 offset++, FALSE, FALSE);
1600 emitcode ("movx", "@%s,a", r->name);
1601 emitcode ("inc", "%s", r->name);
1606 emitcode ("mov", "_spx,%s", r->name);
1608 freeAsmop (NULL, aop, ic, TRUE);
1609 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1612 /*-----------------------------------------------------------------*/
1613 /* genIpush - genrate code for pushing this gets a little complex */
1614 /*-----------------------------------------------------------------*/
1616 genIpush (iCode * ic)
1618 int size, offset = 0;
1622 /* if this is not a parm push : ie. it is spill push
1623 and spill push is always done on the local stack */
1627 /* and the item is spilt then do nothing */
1628 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1631 aopOp (IC_LEFT (ic), ic, FALSE);
1632 size = AOP_SIZE (IC_LEFT (ic));
1633 /* push it on the stack */
1636 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1642 emitcode ("push", "%s", l);
1647 /* this is a paramter push: in this case we call
1648 the routine to find the call and save those
1649 registers that need to be saved */
1652 /* if use external stack then call the external
1653 stack pushing routine */
1654 if (options.useXstack)
1660 /* then do the push */
1661 aopOp (IC_LEFT (ic), ic, FALSE);
1664 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1665 size = AOP_SIZE (IC_LEFT (ic));
1669 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1670 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1671 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1674 emitcode ("mov", "a,%s", l);
1675 emitcode ("push", "acc");
1678 emitcode ("push", "%s", l);
1681 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1684 /*-----------------------------------------------------------------*/
1685 /* genIpop - recover the registers: can happen only for spilling */
1686 /*-----------------------------------------------------------------*/
1688 genIpop (iCode * ic)
1693 /* if the temp was not pushed then */
1694 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1697 aopOp (IC_LEFT (ic), ic, FALSE);
1698 size = AOP_SIZE (IC_LEFT (ic));
1699 offset = (size - 1);
1701 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1704 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1707 /*-----------------------------------------------------------------*/
1708 /* unsaveRBank - restores the resgister bank from stack */
1709 /*-----------------------------------------------------------------*/
1711 unsaveRBank (int bank, iCode * ic, bool popPsw)
1719 if (options.useXstack)
1722 r = getFreePtr (ic, &aop, FALSE);
1725 emitcode ("mov", "%s,_spx", r->name);
1726 emitcode ("movx", "a,@%s", r->name);
1727 emitcode ("mov", "psw,a");
1728 emitcode ("dec", "%s", r->name);
1732 emitcode ("pop", "psw");
1735 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1737 if (options.useXstack)
1739 emitcode ("movx", "a,@%s", r->name);
1740 emitcode ("mov", "(%s+%d),a",
1741 regs8051[i].base, 8 * bank + regs8051[i].offset);
1742 emitcode ("dec", "%s", r->name);
1746 emitcode ("pop", "(%s+%d)",
1747 regs8051[i].base, 8 * bank + regs8051[i].offset);
1750 if (options.useXstack)
1753 emitcode ("mov", "_spx,%s", r->name);
1754 freeAsmop (NULL, aop, ic, TRUE);
1759 /*-----------------------------------------------------------------*/
1760 /* saveRBank - saves an entire register bank on the stack */
1761 /*-----------------------------------------------------------------*/
1763 saveRBank (int bank, iCode * ic, bool pushPsw)
1769 if (options.useXstack)
1773 r = getFreePtr (ic, &aop, FALSE);
1774 emitcode ("mov", "%s,_spx", r->name);
1778 for (i = 0; i < mcs51_nRegs; i++)
1780 if (options.useXstack)
1782 emitcode ("inc", "%s", r->name);
1783 emitcode ("mov", "a,(%s+%d)",
1784 regs8051[i].base, 8 * bank + regs8051[i].offset);
1785 emitcode ("movx", "@%s,a", r->name);
1788 emitcode ("push", "(%s+%d)",
1789 regs8051[i].base, 8 * bank + regs8051[i].offset);
1794 if (options.useXstack)
1796 emitcode ("mov", "a,psw");
1797 emitcode ("movx", "@%s,a", r->name);
1798 emitcode ("inc", "%s", r->name);
1799 emitcode ("mov", "_spx,%s", r->name);
1800 freeAsmop (NULL, aop, ic, TRUE);
1804 emitcode ("push", "psw");
1806 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1812 /*-----------------------------------------------------------------*/
1813 /* genCall - generates a call statement */
1814 /*-----------------------------------------------------------------*/
1816 genCall (iCode * ic)
1820 /* if send set is not empty the assign */
1825 for (sic = setFirstItem (_G.sendSet); sic;
1826 sic = setNextItem (_G.sendSet))
1828 int size, offset = 0;
1829 aopOp (IC_LEFT (sic), sic, FALSE);
1830 size = AOP_SIZE (IC_LEFT (sic));
1833 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1835 if (strcmp (l, fReturn[offset]))
1836 emitcode ("mov", "%s,%s",
1841 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1846 /* if we are calling a function that is not using
1847 the same register bank then we need to save the
1848 destination registers on the stack */
1849 detype = getSpec (operandType (IC_LEFT (ic)));
1851 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1852 IS_ISR (currFunc->etype) &&
1854 saveRBank (SPEC_BANK (detype), ic, TRUE);
1855 } else /* no need to save if we just saved the whole bank */ {
1856 /* if caller saves & we have not saved then */
1862 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1863 OP_SYMBOL (IC_LEFT (ic))->rname :
1864 OP_SYMBOL (IC_LEFT (ic))->name));
1866 /* if we need assign a result value */
1867 if ((IS_ITEMP (IC_RESULT (ic)) &&
1868 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1869 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1870 IS_TRUE_SYMOP (IC_RESULT (ic)))
1874 aopOp (IC_RESULT (ic), ic, FALSE);
1877 assignResultValue (IC_RESULT (ic));
1879 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1882 /* adjust the stack for parameters if
1887 if (ic->parmBytes > 3)
1889 emitcode ("mov", "a,%s", spname);
1890 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1891 emitcode ("mov", "%s,a", spname);
1894 for (i = 0; i < ic->parmBytes; i++)
1895 emitcode ("dec", "%s", spname);
1899 /* if register bank was saved then pop them */
1901 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
1903 /* if we hade saved some registers then unsave them */
1904 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1905 unsaveRegisters (ic);
1910 /*-----------------------------------------------------------------*/
1911 /* genPcall - generates a call by pointer statement */
1912 /*-----------------------------------------------------------------*/
1914 genPcall (iCode * ic)
1917 symbol *rlbl = newiTempLabel (NULL);
1920 /* if caller saves & we have not saved then */
1924 /* if we are calling a function that is not using
1925 the same register bank then we need to save the
1926 destination registers on the stack */
1927 detype = getSpec (operandType (IC_LEFT (ic)));
1929 IS_ISR (currFunc->etype) &&
1930 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1931 saveRBank (SPEC_BANK (detype), ic, TRUE);
1934 /* push the return address on to the stack */
1935 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1936 emitcode ("push", "acc");
1937 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1938 emitcode ("push", "acc");
1940 /* now push the calling address */
1941 aopOp (IC_LEFT (ic), ic, FALSE);
1943 pushSide (IC_LEFT (ic), FPTRSIZE);
1945 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1947 /* if send set is not empty the assign */
1952 for (sic = setFirstItem (_G.sendSet); sic;
1953 sic = setNextItem (_G.sendSet))
1955 int size, offset = 0;
1956 aopOp (IC_LEFT (sic), sic, FALSE);
1957 size = AOP_SIZE (IC_LEFT (sic));
1960 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1962 if (strcmp (l, fReturn[offset]))
1963 emitcode ("mov", "%s,%s",
1968 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1973 emitcode ("ret", "");
1974 emitcode ("", "%05d$:", (rlbl->key + 100));
1977 /* if we need assign a result value */
1978 if ((IS_ITEMP (IC_RESULT (ic)) &&
1979 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1980 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1981 IS_TRUE_SYMOP (IC_RESULT (ic)))
1985 aopOp (IC_RESULT (ic), ic, FALSE);
1988 assignResultValue (IC_RESULT (ic));
1990 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1993 /* adjust the stack for parameters if
1998 if (ic->parmBytes > 3)
2000 emitcode ("mov", "a,%s", spname);
2001 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2002 emitcode ("mov", "%s,a", spname);
2005 for (i = 0; i < ic->parmBytes; i++)
2006 emitcode ("dec", "%s", spname);
2010 /* if register bank was saved then unsave them */
2012 (SPEC_BANK (currFunc->etype) !=
2013 SPEC_BANK (detype)))
2014 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2016 /* if we hade saved some registers then
2019 unsaveRegisters (ic);
2023 /*-----------------------------------------------------------------*/
2024 /* resultRemat - result is rematerializable */
2025 /*-----------------------------------------------------------------*/
2027 resultRemat (iCode * ic)
2029 if (SKIP_IC (ic) || ic->op == IFX)
2032 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2034 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2035 if (sym->remat && !POINTER_SET (ic))
2042 #if defined(__BORLANDC__) || defined(_MSC_VER)
2043 #define STRCASECMP stricmp
2045 #define STRCASECMP strcasecmp
2048 /*-----------------------------------------------------------------*/
2049 /* inExcludeList - return 1 if the string is in exclude Reg list */
2050 /*-----------------------------------------------------------------*/
2052 inExcludeList (char *s)
2056 if (options.excludeRegs[i] &&
2057 STRCASECMP (options.excludeRegs[i], "none") == 0)
2060 for (i = 0; options.excludeRegs[i]; i++)
2062 if (options.excludeRegs[i] &&
2063 STRCASECMP (s, options.excludeRegs[i]) == 0)
2069 /*-----------------------------------------------------------------*/
2070 /* genFunction - generated code for function entry */
2071 /*-----------------------------------------------------------------*/
2073 genFunction (iCode * ic)
2079 /* create the function header */
2080 emitcode (";", "-----------------------------------------");
2081 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2082 emitcode (";", "-----------------------------------------");
2084 emitcode ("", "%s:", sym->rname);
2085 fetype = getSpec (operandType (IC_LEFT (ic)));
2087 /* if critical function then turn interrupts off */
2088 if (SPEC_CRTCL (fetype))
2089 emitcode ("clr", "ea");
2091 /* here we need to generate the equates for the
2092 register bank if required */
2093 if (SPEC_BANK (fetype) != rbank)
2097 rbank = SPEC_BANK (fetype);
2098 for (i = 0; i < mcs51_nRegs; i++)
2100 if (strcmp (regs8051[i].base, "0") == 0)
2101 emitcode ("", "%s = 0x%02x",
2103 8 * rbank + regs8051[i].offset);
2105 emitcode ("", "%s = %s + 0x%02x",
2108 8 * rbank + regs8051[i].offset);
2112 /* if this is an interrupt service routine then
2113 save acc, b, dpl, dph */
2114 if (IS_ISR (sym->etype))
2117 if (!inExcludeList ("acc"))
2118 emitcode ("push", "acc");
2119 if (!inExcludeList ("b"))
2120 emitcode ("push", "b");
2121 if (!inExcludeList ("dpl"))
2122 emitcode ("push", "dpl");
2123 if (!inExcludeList ("dph"))
2124 emitcode ("push", "dph");
2125 /* if this isr has no bank i.e. is going to
2126 run with bank 0 , then we need to save more
2128 if (!SPEC_BANK (sym->etype))
2131 /* if this function does not call any other
2132 function then we can be economical and
2133 save only those registers that are used */
2138 /* if any registers used */
2141 /* save the registers used */
2142 for (i = 0; i < sym->regsUsed->size; i++)
2144 if (bitVectBitValue (sym->regsUsed, i) ||
2145 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2146 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2153 /* this function has a function call cannot
2154 determines register usage so we will have to push the
2156 saveRBank (0, ic, FALSE);
2162 /* if callee-save to be used for this function
2163 then save the registers being used in this function */
2164 if (sym->calleeSave)
2168 /* if any registers used */
2171 /* save the registers used */
2172 for (i = 0; i < sym->regsUsed->size; i++)
2174 if (bitVectBitValue (sym->regsUsed, i) ||
2175 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2177 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2185 /* set the register bank to the desired value */
2186 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2188 emitcode ("push", "psw");
2189 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2192 if (IS_RENT (sym->etype) || options.stackAuto)
2195 if (options.useXstack)
2197 emitcode ("mov", "r0,%s", spname);
2198 emitcode ("mov", "a,_bp");
2199 emitcode ("movx", "@r0,a");
2200 emitcode ("inc", "%s", spname);
2204 /* set up the stack */
2205 emitcode ("push", "_bp"); /* save the callers stack */
2207 emitcode ("mov", "_bp,%s", spname);
2210 /* adjust the stack for the function */
2216 werror (W_STACK_OVERFLOW, sym->name);
2218 if (i > 3 && sym->recvSize < 4)
2221 emitcode ("mov", "a,sp");
2222 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2223 emitcode ("mov", "sp,a");
2228 emitcode ("inc", "sp");
2234 emitcode ("mov", "a,_spx");
2235 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2236 emitcode ("mov", "_spx,a");
2241 /*-----------------------------------------------------------------*/
2242 /* genEndFunction - generates epilogue for functions */
2243 /*-----------------------------------------------------------------*/
2245 genEndFunction (iCode * ic)
2247 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2249 if (IS_RENT (sym->etype) || options.stackAuto)
2251 emitcode ("mov", "%s,_bp", spname);
2254 /* if use external stack but some variables were
2255 added to the local stack then decrement the
2257 if (options.useXstack && sym->stack)
2259 emitcode ("mov", "a,sp");
2260 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2261 emitcode ("mov", "sp,a");
2265 if ((IS_RENT (sym->etype) || options.stackAuto))
2267 if (options.useXstack)
2269 emitcode ("mov", "r0,%s", spname);
2270 emitcode ("movx", "a,@r0");
2271 emitcode ("mov", "_bp,a");
2272 emitcode ("dec", "%s", spname);
2276 emitcode ("pop", "_bp");
2280 /* restore the register bank */
2281 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2282 emitcode ("pop", "psw");
2284 if (IS_ISR (sym->etype))
2287 /* now we need to restore the registers */
2288 /* if this isr has no bank i.e. is going to
2289 run with bank 0 , then we need to save more
2291 if (!SPEC_BANK (sym->etype))
2294 /* if this function does not call any other
2295 function then we can be economical and
2296 save only those registers that are used */
2301 /* if any registers used */
2304 /* save the registers used */
2305 for (i = sym->regsUsed->size; i >= 0; i--)
2307 if (bitVectBitValue (sym->regsUsed, i) ||
2308 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2309 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2316 /* this function has a function call cannot
2317 determines register usage so we will have to pop the
2319 unsaveRBank (0, ic, FALSE);
2323 if (!inExcludeList ("dph"))
2324 emitcode ("pop", "dph");
2325 if (!inExcludeList ("dpl"))
2326 emitcode ("pop", "dpl");
2327 if (!inExcludeList ("b"))
2328 emitcode ("pop", "b");
2329 if (!inExcludeList ("acc"))
2330 emitcode ("pop", "acc");
2332 if (SPEC_CRTCL (sym->etype))
2333 emitcode ("setb", "ea");
2335 /* if debug then send end of function */
2336 /* if (options.debug && currFunc) { */
2340 emitcode ("", "C$%s$%d$%d$%d ==.",
2341 FileBaseName (ic->filename), currFunc->lastLine,
2342 ic->level, ic->block);
2343 if (IS_STATIC (currFunc->etype))
2344 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2346 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2350 emitcode ("reti", "");
2354 if (SPEC_CRTCL (sym->etype))
2355 emitcode ("setb", "ea");
2357 if (sym->calleeSave)
2361 /* if any registers used */
2364 /* save the registers used */
2365 for (i = sym->regsUsed->size; i >= 0; i--)
2367 if (bitVectBitValue (sym->regsUsed, i) ||
2368 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2369 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2375 /* if debug then send end of function */
2379 emitcode ("", "C$%s$%d$%d$%d ==.",
2380 FileBaseName (ic->filename), currFunc->lastLine,
2381 ic->level, ic->block);
2382 if (IS_STATIC (currFunc->etype))
2383 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2385 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2389 emitcode ("ret", "");
2394 /*-----------------------------------------------------------------*/
2395 /* genRet - generate code for return statement */
2396 /*-----------------------------------------------------------------*/
2400 int size, offset = 0, pushed = 0;
2402 /* if we have no return value then
2403 just generate the "ret" */
2407 /* we have something to return then
2408 move the return value into place */
2409 aopOp (IC_LEFT (ic), ic, FALSE);
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2418 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2420 emitcode ("push", "%s", l);
2425 l = aopGet (AOP (IC_LEFT (ic)), offset,
2427 if (strcmp (fReturn[offset], l))
2428 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2437 if (strcmp (fReturn[pushed], "a"))
2438 emitcode ("pop", fReturn[pushed]);
2440 emitcode ("pop", "acc");
2443 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2446 /* generate a jump to the return label
2447 if the next is not the return statement */
2448 if (!(ic->next && ic->next->op == LABEL &&
2449 IC_LABEL (ic->next) == returnLabel))
2451 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2455 /*-----------------------------------------------------------------*/
2456 /* genLabel - generates a label */
2457 /*-----------------------------------------------------------------*/
2459 genLabel (iCode * ic)
2461 /* special case never generate */
2462 if (IC_LABEL (ic) == entryLabel)
2465 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2468 /*-----------------------------------------------------------------*/
2469 /* genGoto - generates a ljmp */
2470 /*-----------------------------------------------------------------*/
2472 genGoto (iCode * ic)
2474 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2477 /*-----------------------------------------------------------------*/
2478 /* findLabelBackwards: walks back through the iCode chain looking */
2479 /* for the given label. Returns number of iCode instructions */
2480 /* between that label and given ic. */
2481 /* Returns zero if label not found. */
2482 /*-----------------------------------------------------------------*/
2484 findLabelBackwards (iCode * ic, int key)
2493 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2495 /* printf("findLabelBackwards = %d\n", count); */
2503 /*-----------------------------------------------------------------*/
2504 /* genPlusIncr :- does addition with increment if possible */
2505 /*-----------------------------------------------------------------*/
2507 genPlusIncr (iCode * ic)
2509 unsigned int icount;
2510 unsigned int size = getDataSize (IC_RESULT (ic));
2512 /* will try to generate an increment */
2513 /* if the right side is not a literal
2515 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2518 /* if the literal value of the right hand side
2519 is greater than 4 then it is not worth it */
2520 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2523 /* if increment 16 bits in register */
2524 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2532 /* If the next instruction is a goto and the goto target
2533 * is < 10 instructions previous to this, we can generate
2534 * jumps straight to that target.
2536 if (ic->next && ic->next->op == GOTO
2537 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2538 && labelRange <= 10)
2540 emitcode (";", "tail increment optimized");
2541 tlbl = IC_LABEL (ic->next);
2546 tlbl = newiTempLabel (NULL);
2549 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2550 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2551 IS_AOP_PREG (IC_RESULT (ic)))
2552 emitcode ("cjne", "%s,#0x00,%05d$"
2553 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2557 emitcode ("clr", "a");
2558 emitcode ("cjne", "a,%s,%05d$"
2559 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2563 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2567 IS_AOP_PREG (IC_RESULT (ic)))
2568 emitcode ("cjne", "%s,#0x00,%05d$"
2569 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2572 emitcode ("cjne", "a,%s,%05d$"
2573 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2576 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2580 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2581 IS_AOP_PREG (IC_RESULT (ic)))
2582 emitcode ("cjne", "%s,#0x00,%05d$"
2583 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2587 emitcode ("cjne", "a,%s,%05d$"
2588 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2591 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2596 emitcode ("", "%05d$:", tlbl->key + 100);
2601 /* if the sizes are greater than 1 then we cannot */
2602 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2603 AOP_SIZE (IC_LEFT (ic)) > 1)
2606 /* we can if the aops of the left & result match or
2607 if they are in registers and the registers are the
2609 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2614 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2615 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2616 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2622 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2631 /*-----------------------------------------------------------------*/
2632 /* outBitAcc - output a bit in acc */
2633 /*-----------------------------------------------------------------*/
2635 outBitAcc (operand * result)
2637 symbol *tlbl = newiTempLabel (NULL);
2638 /* if the result is a bit */
2639 if (AOP_TYPE (result) == AOP_CRY)
2641 aopPut (AOP (result), "a", 0);
2645 emitcode ("jz", "%05d$", tlbl->key + 100);
2646 emitcode ("mov", "a,%s", one);
2647 emitcode ("", "%05d$:", tlbl->key + 100);
2652 /*-----------------------------------------------------------------*/
2653 /* genPlusBits - generates code for addition of two bits */
2654 /*-----------------------------------------------------------------*/
2656 genPlusBits (iCode * ic)
2658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2660 symbol *lbl = newiTempLabel (NULL);
2661 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2662 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2663 emitcode ("cpl", "c");
2664 emitcode ("", "%05d$:", (lbl->key + 100));
2665 outBitC (IC_RESULT (ic));
2669 emitcode ("clr", "a");
2670 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2671 emitcode ("rlc", "a");
2672 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2673 emitcode ("addc", "a,#0x00");
2674 outAcc (IC_RESULT (ic));
2679 /* This is the original version of this code.
2681 * This is being kept around for reference,
2682 * because I am not entirely sure I got it right...
2685 adjustArithmeticResult (iCode * ic)
2687 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2688 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2689 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2690 aopPut (AOP (IC_RESULT (ic)),
2691 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2694 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2695 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2696 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2697 aopPut (AOP (IC_RESULT (ic)),
2698 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2701 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2702 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2703 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2704 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2705 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2708 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2709 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2713 /* This is the pure and virtuous version of this code.
2714 * I'm pretty certain it's right, but not enough to toss the old
2718 adjustArithmeticResult (iCode * ic)
2720 if (opIsGptr (IC_RESULT (ic)) &&
2721 opIsGptr (IC_LEFT (ic)) &&
2722 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2724 aopPut (AOP (IC_RESULT (ic)),
2725 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2729 if (opIsGptr (IC_RESULT (ic)) &&
2730 opIsGptr (IC_RIGHT (ic)) &&
2731 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2733 aopPut (AOP (IC_RESULT (ic)),
2734 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2738 if (opIsGptr (IC_RESULT (ic)) &&
2739 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2740 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2741 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2742 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2745 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2746 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2751 /*-----------------------------------------------------------------*/
2752 /* genPlus - generates code for addition */
2753 /*-----------------------------------------------------------------*/
2755 genPlus (iCode * ic)
2757 int size, offset = 0;
2759 /* special cases :- */
2761 aopOp (IC_LEFT (ic), ic, FALSE);
2762 aopOp (IC_RIGHT (ic), ic, FALSE);
2763 aopOp (IC_RESULT (ic), ic, TRUE);
2765 /* if literal, literal on the right or
2766 if left requires ACC or right is already
2768 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2769 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2770 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2772 operand *t = IC_RIGHT (ic);
2773 IC_RIGHT (ic) = IC_LEFT (ic);
2777 /* if both left & right are in bit
2779 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2780 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2786 /* if left in bit space & right literal */
2787 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2788 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2790 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2791 /* if result in bit space */
2792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2794 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2795 emitcode ("cpl", "c");
2796 outBitC (IC_RESULT (ic));
2800 size = getDataSize (IC_RESULT (ic));
2803 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2804 emitcode ("addc", "a,#00");
2805 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2811 /* if I can do an increment instead
2812 of add then GOOD for ME */
2813 if (genPlusIncr (ic) == TRUE)
2816 size = getDataSize (IC_RESULT (ic));
2820 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2822 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2824 emitcode ("add", "a,%s",
2825 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2827 emitcode ("addc", "a,%s",
2828 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2832 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2834 emitcode ("add", "a,%s",
2835 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2837 emitcode ("addc", "a,%s",
2838 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2840 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2843 adjustArithmeticResult (ic);
2846 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2847 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2851 /*-----------------------------------------------------------------*/
2852 /* genMinusDec :- does subtraction with deccrement if possible */
2853 /*-----------------------------------------------------------------*/
2855 genMinusDec (iCode * ic)
2857 unsigned int icount;
2858 unsigned int size = getDataSize (IC_RESULT (ic));
2860 /* will try to generate an increment */
2861 /* if the right side is not a literal
2863 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2866 /* if the literal value of the right hand side
2867 is greater than 4 then it is not worth it */
2868 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2871 /* if decrement 16 bits in register */
2872 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2880 /* If the next instruction is a goto and the goto target
2881 * is <= 10 instructions previous to this, we can generate
2882 * jumps straight to that target.
2884 if (ic->next && ic->next->op == GOTO
2885 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2886 && labelRange <= 10)
2888 emitcode (";", "tail decrement optimized");
2889 tlbl = IC_LABEL (ic->next);
2894 tlbl = newiTempLabel (NULL);
2898 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2899 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2900 IS_AOP_PREG (IC_RESULT (ic)))
2901 emitcode ("cjne", "%s,#0xff,%05d$"
2902 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2906 emitcode ("mov", "a,#0xff");
2907 emitcode ("cjne", "a,%s,%05d$"
2908 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2911 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2914 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2915 IS_AOP_PREG (IC_RESULT (ic)))
2916 emitcode ("cjne", "%s,#0xff,%05d$"
2917 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2921 emitcode ("cjne", "a,%s,%05d$"
2922 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2925 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2929 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2930 IS_AOP_PREG (IC_RESULT (ic)))
2931 emitcode ("cjne", "%s,#0xff,%05d$"
2932 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2936 emitcode ("cjne", "a,%s,%05d$"
2937 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2940 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2944 emitcode ("", "%05d$:", tlbl->key + 100);
2949 /* if the sizes are greater than 1 then we cannot */
2950 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2951 AOP_SIZE (IC_LEFT (ic)) > 1)
2954 /* we can if the aops of the left & result match or
2955 if they are in registers and the registers are the
2957 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2961 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
2969 /*-----------------------------------------------------------------*/
2970 /* addSign - complete with sign */
2971 /*-----------------------------------------------------------------*/
2973 addSign (operand * result, int offset, int sign)
2975 int size = (getDataSize (result) - offset);
2980 emitcode ("rlc", "a");
2981 emitcode ("subb", "a,acc");
2983 aopPut (AOP (result), "a", offset++);
2987 aopPut (AOP (result), zero, offset++);
2991 /*-----------------------------------------------------------------*/
2992 /* genMinusBits - generates code for subtraction of two bits */
2993 /*-----------------------------------------------------------------*/
2995 genMinusBits (iCode * ic)
2997 symbol *lbl = newiTempLabel (NULL);
2998 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3000 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3001 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3002 emitcode ("cpl", "c");
3003 emitcode ("", "%05d$:", (lbl->key + 100));
3004 outBitC (IC_RESULT (ic));
3008 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3009 emitcode ("subb", "a,acc");
3010 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3011 emitcode ("inc", "a");
3012 emitcode ("", "%05d$:", (lbl->key + 100));
3013 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3014 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3018 /*-----------------------------------------------------------------*/
3019 /* genMinus - generates code for subtraction */
3020 /*-----------------------------------------------------------------*/
3022 genMinus (iCode * ic)
3024 int size, offset = 0;
3025 unsigned long lit = 0L;
3027 aopOp (IC_LEFT (ic), ic, FALSE);
3028 aopOp (IC_RIGHT (ic), ic, FALSE);
3029 aopOp (IC_RESULT (ic), ic, TRUE);
3031 /* special cases :- */
3032 /* if both left & right are in bit space */
3033 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3034 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3040 /* if I can do an decrement instead
3041 of subtract then GOOD for ME */
3042 if (genMinusDec (ic) == TRUE)
3045 size = getDataSize (IC_RESULT (ic));
3047 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3053 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3057 /* if literal, add a,#-lit, else normal subb */
3060 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3061 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3062 emitcode ("subb", "a,%s",
3063 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3066 /* first add without previous c */
3068 emitcode ("add", "a,#0x%02x",
3069 (unsigned int) (lit & 0x0FFL));
3071 emitcode ("addc", "a,#0x%02x",
3072 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3074 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3077 adjustArithmeticResult (ic);
3080 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3081 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3082 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3086 /*-----------------------------------------------------------------*/
3087 /* genMultbits :- multiplication of bits */
3088 /*-----------------------------------------------------------------*/
3090 genMultbits (operand * left,
3094 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3095 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3100 /*-----------------------------------------------------------------*/
3101 /* genMultOneByte : 8*8=8/16 bit multiplication */
3102 /*-----------------------------------------------------------------*/
3104 genMultOneByte (operand * left,
3108 sym_link *opetype = operandType (result);
3110 int size=AOP_SIZE(result);
3112 //emitcode (";",__FUNCTION__);
3113 if (size<1 || size>2) {
3114 // this should never happen
3115 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3116 AOP_SIZE(result), __FUNCTION__, lineno);
3120 /* (if two literals: the value is computed before) */
3121 /* if one literal, literal on the right */
3122 if (AOP_TYPE (left) == AOP_LIT)
3127 //emitcode (";", "swapped left and right");
3130 if (SPEC_USIGN(opetype)
3131 // ignore the sign of left and right, what else can we do?
3132 || (SPEC_USIGN(operandType(left)) &&
3133 SPEC_USIGN(operandType(right)))) {
3134 // just an unsigned 8*8=8/16 multiply
3135 //emitcode (";","unsigned");
3136 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3137 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3138 emitcode ("mul", "ab");
3139 aopPut (AOP (result), "a", 0);
3141 aopPut (AOP (result), "b", 1);
3146 // we have to do a signed multiply
3148 //emitcode (";", "signed");
3149 emitcode ("clr", "F0"); // reset sign flag
3150 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3151 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3153 lbl=newiTempLabel(NULL);
3154 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3155 // left side is negative, 8-bit two's complement, this fails for -128
3156 emitcode ("setb", "F0"); // set sign flag
3157 emitcode ("cpl", "a");
3158 emitcode ("inc", "a");
3160 emitcode ("", "%05d$:", lbl->key+100);
3161 emitcode ("xch", "a,b");
3164 if (AOP_TYPE(right)==AOP_LIT) {
3165 /* AND literal negative */
3166 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3167 // two's complement for literal<0
3168 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3169 emitcode ("cpl", "a");
3170 emitcode ("inc", "a");
3173 lbl=newiTempLabel(NULL);
3174 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3175 // right side is negative, 8-bit two's complement
3176 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3177 emitcode ("cpl", "a");
3178 emitcode ("inc", "a");
3179 emitcode ("", "%05d$:", lbl->key+100);
3181 emitcode ("mul", "ab");
3183 lbl=newiTempLabel(NULL);
3184 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3185 // only ONE op was negative, we have to do a 8/16-bit two's complement
3186 emitcode ("cpl", "a"); // lsb
3188 emitcode ("inc", "a");
3190 emitcode ("add", "a,#1");
3191 emitcode ("xch", "a,b");
3192 emitcode ("cpl", "a"); // msb
3193 emitcode ("addc", "a,#0");
3194 emitcode ("xch", "a,b");
3197 emitcode ("", "%05d$:", lbl->key+100);
3198 aopPut (AOP (result), "a", 0);
3200 aopPut (AOP (result), "b", 1);
3204 /*-----------------------------------------------------------------*/
3205 /* genMult - generates code for multiplication */
3206 /*-----------------------------------------------------------------*/
3208 genMult (iCode * ic)
3210 operand *left = IC_LEFT (ic);
3211 operand *right = IC_RIGHT (ic);
3212 operand *result = IC_RESULT (ic);
3214 /* assign the amsops */
3215 aopOp (left, ic, FALSE);
3216 aopOp (right, ic, FALSE);
3217 aopOp (result, ic, TRUE);
3219 /* special cases first */
3221 if (AOP_TYPE (left) == AOP_CRY &&
3222 AOP_TYPE (right) == AOP_CRY)
3224 genMultbits (left, right, result);
3228 /* if both are of size == 1 */
3229 if (AOP_SIZE (left) == 1 &&
3230 AOP_SIZE (right) == 1)
3232 genMultOneByte (left, right, result);
3236 /* should have been converted to function call */
3240 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3241 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3242 freeAsmop (result, NULL, ic, TRUE);
3245 /*-----------------------------------------------------------------*/
3246 /* genDivbits :- division of bits */
3247 /*-----------------------------------------------------------------*/
3249 genDivbits (operand * left,
3256 /* the result must be bit */
3257 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3258 l = aopGet (AOP (left), 0, FALSE, FALSE);
3262 emitcode ("div", "ab");
3263 emitcode ("rrc", "a");
3264 aopPut (AOP (result), "c", 0);
3267 /*-----------------------------------------------------------------*/
3268 /* genDivOneByte : 8 bit division */
3269 /*-----------------------------------------------------------------*/
3271 genDivOneByte (operand * left,
3275 sym_link *opetype = operandType (result);
3280 size = AOP_SIZE (result) - 1;
3282 /* signed or unsigned */
3283 if (SPEC_USIGN (opetype))
3285 /* unsigned is easy */
3286 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3287 l = aopGet (AOP (left), 0, FALSE, FALSE);
3289 emitcode ("div", "ab");
3290 aopPut (AOP (result), "a", 0);
3292 aopPut (AOP (result), zero, offset++);
3296 /* signed is a little bit more difficult */
3298 /* save the signs of the operands */
3299 l = aopGet (AOP (left), 0, FALSE, FALSE);
3301 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3302 emitcode ("push", "acc"); /* save it on the stack */
3304 /* now sign adjust for both left & right */
3305 l = aopGet (AOP (right), 0, FALSE, FALSE);
3307 lbl = newiTempLabel (NULL);
3308 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3309 emitcode ("cpl", "a");
3310 emitcode ("inc", "a");
3311 emitcode ("", "%05d$:", (lbl->key + 100));
3312 emitcode ("mov", "b,a");
3314 /* sign adjust left side */
3315 l = aopGet (AOP (left), 0, FALSE, FALSE);
3318 lbl = newiTempLabel (NULL);
3319 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3320 emitcode ("cpl", "a");
3321 emitcode ("inc", "a");
3322 emitcode ("", "%05d$:", (lbl->key + 100));
3324 /* now the division */
3325 emitcode ("div", "ab");
3326 /* we are interested in the lower order
3328 emitcode ("mov", "b,a");
3329 lbl = newiTempLabel (NULL);
3330 emitcode ("pop", "acc");
3331 /* if there was an over flow we don't
3332 adjust the sign of the result */
3333 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3334 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3336 emitcode ("clr", "a");
3337 emitcode ("subb", "a,b");
3338 emitcode ("mov", "b,a");
3339 emitcode ("", "%05d$:", (lbl->key + 100));
3341 /* now we are done */
3342 aopPut (AOP (result), "b", 0);
3345 emitcode ("mov", "c,b.7");
3346 emitcode ("subb", "a,acc");
3349 aopPut (AOP (result), "a", offset++);
3353 /*-----------------------------------------------------------------*/
3354 /* genDiv - generates code for division */
3355 /*-----------------------------------------------------------------*/
3359 operand *left = IC_LEFT (ic);
3360 operand *right = IC_RIGHT (ic);
3361 operand *result = IC_RESULT (ic);
3363 /* assign the amsops */
3364 aopOp (left, ic, FALSE);
3365 aopOp (right, ic, FALSE);
3366 aopOp (result, ic, TRUE);
3368 /* special cases first */
3370 if (AOP_TYPE (left) == AOP_CRY &&
3371 AOP_TYPE (right) == AOP_CRY)
3373 genDivbits (left, right, result);
3377 /* if both are of size == 1 */
3378 if (AOP_SIZE (left) == 1 &&
3379 AOP_SIZE (right) == 1)
3381 genDivOneByte (left, right, result);
3385 /* should have been converted to function call */
3388 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3389 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3390 freeAsmop (result, NULL, ic, TRUE);
3393 /*-----------------------------------------------------------------*/
3394 /* genModbits :- modulus of bits */
3395 /*-----------------------------------------------------------------*/
3397 genModbits (operand * left,
3404 /* the result must be bit */
3405 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3406 l = aopGet (AOP (left), 0, FALSE, FALSE);
3410 emitcode ("div", "ab");
3411 emitcode ("mov", "a,b");
3412 emitcode ("rrc", "a");
3413 aopPut (AOP (result), "c", 0);
3416 /*-----------------------------------------------------------------*/
3417 /* genModOneByte : 8 bit modulus */
3418 /*-----------------------------------------------------------------*/
3420 genModOneByte (operand * left,
3424 sym_link *opetype = operandType (result);
3428 /* signed or unsigned */
3429 if (SPEC_USIGN (opetype))
3431 /* unsigned is easy */
3432 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3433 l = aopGet (AOP (left), 0, FALSE, FALSE);
3435 emitcode ("div", "ab");
3436 aopPut (AOP (result), "b", 0);
3440 /* signed is a little bit more difficult */
3442 /* save the signs of the operands */
3443 l = aopGet (AOP (left), 0, FALSE, FALSE);
3446 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3447 emitcode ("push", "acc"); /* save it on the stack */
3449 /* now sign adjust for both left & right */
3450 l = aopGet (AOP (right), 0, FALSE, FALSE);
3453 lbl = newiTempLabel (NULL);
3454 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3455 emitcode ("cpl", "a");
3456 emitcode ("inc", "a");
3457 emitcode ("", "%05d$:", (lbl->key + 100));
3458 emitcode ("mov", "b,a");
3460 /* sign adjust left side */
3461 l = aopGet (AOP (left), 0, FALSE, FALSE);
3464 lbl = newiTempLabel (NULL);
3465 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3466 emitcode ("cpl", "a");
3467 emitcode ("inc", "a");
3468 emitcode ("", "%05d$:", (lbl->key + 100));
3470 /* now the multiplication */
3471 emitcode ("div", "ab");
3472 /* we are interested in the lower order
3474 lbl = newiTempLabel (NULL);
3475 emitcode ("pop", "acc");
3476 /* if there was an over flow we don't
3477 adjust the sign of the result */
3478 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3479 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3481 emitcode ("clr", "a");
3482 emitcode ("subb", "a,b");
3483 emitcode ("mov", "b,a");
3484 emitcode ("", "%05d$:", (lbl->key + 100));
3486 /* now we are done */
3487 aopPut (AOP (result), "b", 0);
3491 /*-----------------------------------------------------------------*/
3492 /* genMod - generates code for division */
3493 /*-----------------------------------------------------------------*/
3497 operand *left = IC_LEFT (ic);
3498 operand *right = IC_RIGHT (ic);
3499 operand *result = IC_RESULT (ic);
3501 /* assign the amsops */
3502 aopOp (left, ic, FALSE);
3503 aopOp (right, ic, FALSE);
3504 aopOp (result, ic, TRUE);
3506 /* special cases first */
3508 if (AOP_TYPE (left) == AOP_CRY &&
3509 AOP_TYPE (right) == AOP_CRY)
3511 genModbits (left, right, result);
3515 /* if both are of size == 1 */
3516 if (AOP_SIZE (left) == 1 &&
3517 AOP_SIZE (right) == 1)
3519 genModOneByte (left, right, result);
3523 /* should have been converted to function call */
3527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3528 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3529 freeAsmop (result, NULL, ic, TRUE);
3532 /*-----------------------------------------------------------------*/
3533 /* genIfxJump :- will create a jump depending on the ifx */
3534 /*-----------------------------------------------------------------*/
3536 genIfxJump (iCode * ic, char *jval)
3539 symbol *tlbl = newiTempLabel (NULL);
3542 /* if true label then we jump if condition
3546 jlbl = IC_TRUE (ic);
3547 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3548 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3552 /* false label is present */
3553 jlbl = IC_FALSE (ic);
3554 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3555 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3557 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3558 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3560 emitcode (inst, "%05d$", tlbl->key + 100);
3561 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3562 emitcode ("", "%05d$:", tlbl->key + 100);
3564 /* mark the icode as generated */
3568 /*-----------------------------------------------------------------*/
3569 /* genCmp :- greater or less than comparison */
3570 /*-----------------------------------------------------------------*/
3572 genCmp (operand * left, operand * right,
3573 operand * result, iCode * ifx, int sign, iCode *ic)
3575 int size, offset = 0;
3576 unsigned long lit = 0L;
3578 /* if left & right are bit variables */
3579 if (AOP_TYPE (left) == AOP_CRY &&
3580 AOP_TYPE (right) == AOP_CRY)
3582 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3583 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3587 /* subtract right from left if at the
3588 end the carry flag is set then we know that
3589 left is greater than right */
3590 size = max (AOP_SIZE (left), AOP_SIZE (right));
3592 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3593 if ((size == 1) && !sign &&
3594 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3596 symbol *lbl = newiTempLabel (NULL);
3597 emitcode ("cjne", "%s,%s,%05d$",
3598 aopGet (AOP (left), offset, FALSE, FALSE),
3599 aopGet (AOP (right), offset, FALSE, FALSE),
3601 emitcode ("", "%05d$:", lbl->key + 100);
3605 if (AOP_TYPE (right) == AOP_LIT)
3607 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3608 /* optimize if(x < 0) or if(x >= 0) */
3617 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3618 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3620 genIfxJump (ifx, "acc.7");
3624 emitcode ("rlc", "a");
3632 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3633 if (sign && size == 0)
3635 emitcode ("xrl", "a,#0x80");
3636 if (AOP_TYPE (right) == AOP_LIT)
3638 unsigned long lit = (unsigned long)
3639 floatFromVal (AOP (right)->aopu.aop_lit);
3640 emitcode ("subb", "a,#0x%02x",
3641 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3645 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3646 emitcode ("xrl", "b,#0x80");
3647 emitcode ("subb", "a,b");
3651 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3657 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3658 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3659 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3665 /* if the result is used in the next
3666 ifx conditional branch then generate
3667 code a little differently */
3669 genIfxJump (ifx, "c");
3672 /* leave the result in acc */
3676 /*-----------------------------------------------------------------*/
3677 /* genCmpGt :- greater than comparison */
3678 /*-----------------------------------------------------------------*/
3680 genCmpGt (iCode * ic, iCode * ifx)
3682 operand *left, *right, *result;
3683 sym_link *letype, *retype;
3686 left = IC_LEFT (ic);
3687 right = IC_RIGHT (ic);
3688 result = IC_RESULT (ic);
3690 letype = getSpec (operandType (left));
3691 retype = getSpec (operandType (right));
3692 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3693 /* assign the amsops */
3694 aopOp (left, ic, FALSE);
3695 aopOp (right, ic, FALSE);
3696 aopOp (result, ic, TRUE);
3698 genCmp (right, left, result, ifx, sign,ic);
3700 freeAsmop (result, NULL, ic, TRUE);
3703 /*-----------------------------------------------------------------*/
3704 /* genCmpLt - less than comparisons */
3705 /*-----------------------------------------------------------------*/
3707 genCmpLt (iCode * ic, iCode * ifx)
3709 operand *left, *right, *result;
3710 sym_link *letype, *retype;
3713 left = IC_LEFT (ic);
3714 right = IC_RIGHT (ic);
3715 result = IC_RESULT (ic);
3717 letype = getSpec (operandType (left));
3718 retype = getSpec (operandType (right));
3719 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3721 /* assign the amsops */
3722 aopOp (left, ic, FALSE);
3723 aopOp (right, ic, FALSE);
3724 aopOp (result, ic, TRUE);
3726 genCmp (left, right, result, ifx, sign,ic);
3728 freeAsmop (result, NULL, ic, TRUE);
3731 /*-----------------------------------------------------------------*/
3732 /* gencjneshort - compare and jump if not equal */
3733 /*-----------------------------------------------------------------*/
3735 gencjneshort (operand * left, operand * right, symbol * lbl)
3737 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3739 unsigned long lit = 0L;
3741 /* if the left side is a literal or
3742 if the right is in a pointer register and left
3744 if ((AOP_TYPE (left) == AOP_LIT) ||
3745 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3751 if (AOP_TYPE (right) == AOP_LIT)
3752 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3754 /* if the right side is a literal then anything goes */
3755 if (AOP_TYPE (right) == AOP_LIT &&
3756 AOP_TYPE (left) != AOP_DIR)
3760 emitcode ("cjne", "%s,%s,%05d$",
3761 aopGet (AOP (left), offset, FALSE, FALSE),
3762 aopGet (AOP (right), offset, FALSE, FALSE),
3768 /* if the right side is in a register or in direct space or
3769 if the left is a pointer register & right is not */
3770 else if (AOP_TYPE (right) == AOP_REG ||
3771 AOP_TYPE (right) == AOP_DIR ||
3772 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3773 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3777 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3778 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3779 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3780 emitcode ("jnz", "%05d$", lbl->key + 100);
3782 emitcode ("cjne", "a,%s,%05d$",
3783 aopGet (AOP (right), offset, FALSE, TRUE),
3790 /* right is a pointer reg need both a & b */
3793 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3794 if (strcmp (l, "b"))
3795 emitcode ("mov", "b,%s", l);
3796 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3797 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3803 /*-----------------------------------------------------------------*/
3804 /* gencjne - compare and jump if not equal */
3805 /*-----------------------------------------------------------------*/
3807 gencjne (operand * left, operand * right, symbol * lbl)
3809 symbol *tlbl = newiTempLabel (NULL);
3811 gencjneshort (left, right, lbl);
3813 emitcode ("mov", "a,%s", one);
3814 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3815 emitcode ("", "%05d$:", lbl->key + 100);
3816 emitcode ("clr", "a");
3817 emitcode ("", "%05d$:", tlbl->key + 100);
3820 /*-----------------------------------------------------------------*/
3821 /* genCmpEq - generates code for equal to */
3822 /*-----------------------------------------------------------------*/
3824 genCmpEq (iCode * ic, iCode * ifx)
3826 operand *left, *right, *result;
3828 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3829 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3830 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3832 /* if literal, literal on the right or
3833 if the right is in a pointer register and left
3835 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3836 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3838 operand *t = IC_RIGHT (ic);
3839 IC_RIGHT (ic) = IC_LEFT (ic);
3843 if (ifx && !AOP_SIZE (result))
3846 /* if they are both bit variables */
3847 if (AOP_TYPE (left) == AOP_CRY &&
3848 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3850 if (AOP_TYPE (right) == AOP_LIT)
3852 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3855 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3856 emitcode ("cpl", "c");
3860 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3864 emitcode ("clr", "c");
3866 /* AOP_TYPE(right) == AOP_CRY */
3870 symbol *lbl = newiTempLabel (NULL);
3871 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3872 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3873 emitcode ("cpl", "c");
3874 emitcode ("", "%05d$:", (lbl->key + 100));
3876 /* if true label then we jump if condition
3878 tlbl = newiTempLabel (NULL);
3881 emitcode ("jnc", "%05d$", tlbl->key + 100);
3882 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3886 emitcode ("jc", "%05d$", tlbl->key + 100);
3887 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3889 emitcode ("", "%05d$:", tlbl->key + 100);
3893 tlbl = newiTempLabel (NULL);
3894 gencjneshort (left, right, tlbl);
3897 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3898 emitcode ("", "%05d$:", tlbl->key + 100);
3902 symbol *lbl = newiTempLabel (NULL);
3903 emitcode ("sjmp", "%05d$", lbl->key + 100);
3904 emitcode ("", "%05d$:", tlbl->key + 100);
3905 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3906 emitcode ("", "%05d$:", lbl->key + 100);
3909 /* mark the icode as generated */
3914 /* if they are both bit variables */
3915 if (AOP_TYPE (left) == AOP_CRY &&
3916 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3918 if (AOP_TYPE (right) == AOP_LIT)
3920 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3923 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3924 emitcode ("cpl", "c");
3928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3932 emitcode ("clr", "c");
3934 /* AOP_TYPE(right) == AOP_CRY */
3938 symbol *lbl = newiTempLabel (NULL);
3939 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3940 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3941 emitcode ("cpl", "c");
3942 emitcode ("", "%05d$:", (lbl->key + 100));
3945 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3952 genIfxJump (ifx, "c");
3955 /* if the result is used in an arithmetic operation
3956 then put the result in place */
3961 gencjne (left, right, newiTempLabel (NULL));
3962 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3964 aopPut (AOP (result), "a", 0);
3969 genIfxJump (ifx, "a");
3972 /* if the result is used in an arithmetic operation
3973 then put the result in place */
3974 if (AOP_TYPE (result) != AOP_CRY)
3976 /* leave the result in acc */
3980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3982 freeAsmop (result, NULL, ic, TRUE);
3985 /*-----------------------------------------------------------------*/
3986 /* ifxForOp - returns the icode containing the ifx for operand */
3987 /*-----------------------------------------------------------------*/
3989 ifxForOp (operand * op, iCode * ic)
3991 /* if true symbol then needs to be assigned */
3992 if (IS_TRUE_SYMOP (op))
3995 /* if this has register type condition and
3996 the next instruction is ifx with the same operand
3997 and live to of the operand is upto the ifx only then */
3999 ic->next->op == IFX &&
4000 IC_COND (ic->next)->key == op->key &&
4001 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4007 /*-----------------------------------------------------------------*/
4008 /* hasInc - operand is incremented before any other use */
4009 /*-----------------------------------------------------------------*/
4011 hasInc (operand *op, iCode *ic)
4013 sym_link *type = operandType(op);
4014 sym_link *retype = getSpec (type);
4015 iCode *lic = ic->next;
4018 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4019 isize = getSize(type->next);
4021 /* if operand of the form op = op + <sizeof *op> */
4022 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4023 isOperandEqual(IC_RESULT(lic),op) &&
4024 isOperandLiteral(IC_RIGHT(lic)) &&
4025 operandLitValue(IC_RIGHT(lic)) == isize) {
4028 /* if the operand used or deffed */
4029 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4037 /*-----------------------------------------------------------------*/
4038 /* genAndOp - for && operation */
4039 /*-----------------------------------------------------------------*/
4041 genAndOp (iCode * ic)
4043 operand *left, *right, *result;
4046 /* note here that && operations that are in an
4047 if statement are taken away by backPatchLabels
4048 only those used in arthmetic operations remain */
4049 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4050 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4051 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4053 /* if both are bit variables */
4054 if (AOP_TYPE (left) == AOP_CRY &&
4055 AOP_TYPE (right) == AOP_CRY)
4057 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4058 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4063 tlbl = newiTempLabel (NULL);
4065 emitcode ("jz", "%05d$", tlbl->key + 100);
4067 emitcode ("", "%05d$:", tlbl->key + 100);
4071 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4072 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4073 freeAsmop (result, NULL, ic, TRUE);
4077 /*-----------------------------------------------------------------*/
4078 /* genOrOp - for || operation */
4079 /*-----------------------------------------------------------------*/
4081 genOrOp (iCode * ic)
4083 operand *left, *right, *result;
4086 /* note here that || operations that are in an
4087 if statement are taken away by backPatchLabels
4088 only those used in arthmetic operations remain */
4089 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4090 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4091 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4093 /* if both are bit variables */
4094 if (AOP_TYPE (left) == AOP_CRY &&
4095 AOP_TYPE (right) == AOP_CRY)
4097 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4098 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4103 tlbl = newiTempLabel (NULL);
4105 emitcode ("jnz", "%05d$", tlbl->key + 100);
4107 emitcode ("", "%05d$:", tlbl->key + 100);
4111 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4112 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4113 freeAsmop (result, NULL, ic, TRUE);
4116 /*-----------------------------------------------------------------*/
4117 /* isLiteralBit - test if lit == 2^n */
4118 /*-----------------------------------------------------------------*/
4120 isLiteralBit (unsigned long lit)
4122 unsigned long pw[32] =
4123 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4124 0x100L, 0x200L, 0x400L, 0x800L,
4125 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4126 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4127 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4128 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4129 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4132 for (idx = 0; idx < 32; idx++)
4138 /*-----------------------------------------------------------------*/
4139 /* continueIfTrue - */
4140 /*-----------------------------------------------------------------*/
4142 continueIfTrue (iCode * ic)
4145 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4149 /*-----------------------------------------------------------------*/
4151 /*-----------------------------------------------------------------*/
4153 jumpIfTrue (iCode * ic)
4156 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4160 /*-----------------------------------------------------------------*/
4161 /* jmpTrueOrFalse - */
4162 /*-----------------------------------------------------------------*/
4164 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4166 // ugly but optimized by peephole
4169 symbol *nlbl = newiTempLabel (NULL);
4170 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4171 emitcode ("", "%05d$:", tlbl->key + 100);
4172 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4173 emitcode ("", "%05d$:", nlbl->key + 100);
4177 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4178 emitcode ("", "%05d$:", tlbl->key + 100);
4183 /*-----------------------------------------------------------------*/
4184 /* genAnd - code for and */
4185 /*-----------------------------------------------------------------*/
4187 genAnd (iCode * ic, iCode * ifx)
4189 operand *left, *right, *result;
4190 int size, offset = 0;
4191 unsigned long lit = 0L;
4195 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4196 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4197 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4200 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4202 AOP_TYPE (left), AOP_TYPE (right));
4203 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4205 AOP_SIZE (left), AOP_SIZE (right));
4208 /* if left is a literal & right is not then exchange them */
4209 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4210 AOP_NEEDSACC (left))
4212 operand *tmp = right;
4217 /* if result = right then exchange them */
4218 if (sameRegs (AOP (result), AOP (right)))
4220 operand *tmp = right;
4225 /* if right is bit then exchange them */
4226 if (AOP_TYPE (right) == AOP_CRY &&
4227 AOP_TYPE (left) != AOP_CRY)
4229 operand *tmp = right;
4233 if (AOP_TYPE (right) == AOP_LIT)
4234 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4236 size = AOP_SIZE (result);
4239 // result = bit & yy;
4240 if (AOP_TYPE (left) == AOP_CRY)
4242 // c = bit & literal;
4243 if (AOP_TYPE (right) == AOP_LIT)
4247 if (size && sameRegs (AOP (result), AOP (left)))
4250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4255 if (size && (AOP_TYPE (result) == AOP_CRY))
4257 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4260 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4265 emitcode ("clr", "c");
4270 if (AOP_TYPE (right) == AOP_CRY)
4273 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4274 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4279 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4281 emitcode ("rrc", "a");
4282 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4290 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4291 genIfxJump (ifx, "c");
4295 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4296 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4297 if ((AOP_TYPE (right) == AOP_LIT) &&
4298 (AOP_TYPE (result) == AOP_CRY) &&
4299 (AOP_TYPE (left) != AOP_CRY))
4301 int posbit = isLiteralBit (lit);
4306 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4309 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4315 sprintf (buffer, "acc.%d", posbit & 0x07);
4316 genIfxJump (ifx, buffer);
4323 symbol *tlbl = newiTempLabel (NULL);
4324 int sizel = AOP_SIZE (left);
4326 emitcode ("setb", "c");
4329 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4331 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4333 if ((posbit = isLiteralBit (bytelit)) != 0)
4334 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4337 if (bytelit != 0x0FFL)
4338 emitcode ("anl", "a,%s",
4339 aopGet (AOP (right), offset, FALSE, TRUE));
4340 emitcode ("jnz", "%05d$", tlbl->key + 100);
4345 // bit = left & literal
4348 emitcode ("clr", "c");
4349 emitcode ("", "%05d$:", tlbl->key + 100);
4351 // if(left & literal)
4355 jmpTrueOrFalse (ifx, tlbl);
4363 /* if left is same as result */
4364 if (sameRegs (AOP (result), AOP (left)))
4366 for (; size--; offset++)
4368 if (AOP_TYPE (right) == AOP_LIT)
4370 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4372 else if (bytelit == 0)
4373 aopPut (AOP (result), zero, offset);
4374 else if (IS_AOP_PREG (result))
4376 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4377 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4378 aopPut (AOP (result), "a", offset);
4381 emitcode ("anl", "%s,%s",
4382 aopGet (AOP (left), offset, FALSE, TRUE),
4383 aopGet (AOP (right), offset, FALSE, FALSE));
4387 if (AOP_TYPE (left) == AOP_ACC)
4388 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4392 if (IS_AOP_PREG (result))
4394 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4395 aopPut (AOP (result), "a", offset);
4399 emitcode ("anl", "%s,a",
4400 aopGet (AOP (left), offset, FALSE, TRUE));
4407 // left & result in different registers
4408 if (AOP_TYPE (result) == AOP_CRY)
4411 // if(size), result in bit
4412 // if(!size && ifx), conditional oper: if(left & right)
4413 symbol *tlbl = newiTempLabel (NULL);
4414 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4416 emitcode ("setb", "c");
4419 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4420 emitcode ("anl", "a,%s",
4421 aopGet (AOP (left), offset, FALSE, FALSE));
4422 emitcode ("jnz", "%05d$", tlbl->key + 100);
4428 emitcode ("", "%05d$:", tlbl->key + 100);
4432 jmpTrueOrFalse (ifx, tlbl);
4436 for (; (size--); offset++)
4439 // result = left & right
4440 if (AOP_TYPE (right) == AOP_LIT)
4442 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4444 aopPut (AOP (result),
4445 aopGet (AOP (left), offset, FALSE, FALSE),
4449 else if (bytelit == 0)
4451 aopPut (AOP (result), zero, offset);
4455 // faster than result <- left, anl result,right
4456 // and better if result is SFR
4457 if (AOP_TYPE (left) == AOP_ACC)
4458 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4462 emitcode ("anl", "a,%s",
4463 aopGet (AOP (left), offset, FALSE, FALSE));
4465 aopPut (AOP (result), "a", offset);
4471 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (result, NULL, ic, TRUE);
4476 /*-----------------------------------------------------------------*/
4477 /* genOr - code for or */
4478 /*-----------------------------------------------------------------*/
4480 genOr (iCode * ic, iCode * ifx)
4482 operand *left, *right, *result;
4483 int size, offset = 0;
4484 unsigned long lit = 0L;
4486 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4487 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4488 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4491 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4493 AOP_TYPE (left), AOP_TYPE (right));
4494 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4496 AOP_SIZE (left), AOP_SIZE (right));
4499 /* if left is a literal & right is not then exchange them */
4500 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4501 AOP_NEEDSACC (left))
4503 operand *tmp = right;
4508 /* if result = right then exchange them */
4509 if (sameRegs (AOP (result), AOP (right)))
4511 operand *tmp = right;
4516 /* if right is bit then exchange them */
4517 if (AOP_TYPE (right) == AOP_CRY &&
4518 AOP_TYPE (left) != AOP_CRY)
4520 operand *tmp = right;
4524 if (AOP_TYPE (right) == AOP_LIT)
4525 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4527 size = AOP_SIZE (result);
4531 if (AOP_TYPE (left) == AOP_CRY)
4533 if (AOP_TYPE (right) == AOP_LIT)
4535 // c = bit & literal;
4538 // lit != 0 => result = 1
4539 if (AOP_TYPE (result) == AOP_CRY)
4542 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4544 continueIfTrue (ifx);
4547 emitcode ("setb", "c");
4551 // lit == 0 => result = left
4552 if (size && sameRegs (AOP (result), AOP (left)))
4554 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4559 if (AOP_TYPE (right) == AOP_CRY)
4562 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4563 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4568 symbol *tlbl = newiTempLabel (NULL);
4569 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4570 emitcode ("setb", "c");
4571 emitcode ("jb", "%s,%05d$",
4572 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4574 emitcode ("jnz", "%05d$", tlbl->key + 100);
4575 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4577 jmpTrueOrFalse (ifx, tlbl);
4583 emitcode ("", "%05d$:", tlbl->key + 100);
4592 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4593 genIfxJump (ifx, "c");
4597 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4598 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4599 if ((AOP_TYPE (right) == AOP_LIT) &&
4600 (AOP_TYPE (result) == AOP_CRY) &&
4601 (AOP_TYPE (left) != AOP_CRY))
4607 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4609 continueIfTrue (ifx);
4614 // lit = 0, result = boolean(left)
4616 emitcode ("setb", "c");
4620 symbol *tlbl = newiTempLabel (NULL);
4621 emitcode ("jnz", "%05d$", tlbl->key + 100);
4623 emitcode ("", "%05d$:", tlbl->key + 100);
4627 genIfxJump (ifx, "a");
4635 /* if left is same as result */
4636 if (sameRegs (AOP (result), AOP (left)))
4638 for (; size--; offset++)
4640 if (AOP_TYPE (right) == AOP_LIT)
4642 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4644 else if (IS_AOP_PREG (left))
4646 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4647 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4648 aopPut (AOP (result), "a", offset);
4651 emitcode ("orl", "%s,%s",
4652 aopGet (AOP (left), offset, FALSE, TRUE),
4653 aopGet (AOP (right), offset, FALSE, FALSE));
4657 if (AOP_TYPE (left) == AOP_ACC)
4658 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4661 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4662 if (IS_AOP_PREG (left))
4664 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4665 aopPut (AOP (result), "a", offset);
4668 emitcode ("orl", "%s,a",
4669 aopGet (AOP (left), offset, FALSE, TRUE));
4676 // left & result in different registers
4677 if (AOP_TYPE (result) == AOP_CRY)
4680 // if(size), result in bit
4681 // if(!size && ifx), conditional oper: if(left | right)
4682 symbol *tlbl = newiTempLabel (NULL);
4683 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4685 emitcode ("setb", "c");
4688 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4689 emitcode ("orl", "a,%s",
4690 aopGet (AOP (left), offset, FALSE, FALSE));
4691 emitcode ("jnz", "%05d$", tlbl->key + 100);
4697 emitcode ("", "%05d$:", tlbl->key + 100);
4701 jmpTrueOrFalse (ifx, tlbl);
4704 for (; (size--); offset++)
4707 // result = left & right
4708 if (AOP_TYPE (right) == AOP_LIT)
4710 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4712 aopPut (AOP (result),
4713 aopGet (AOP (left), offset, FALSE, FALSE),
4718 // faster than result <- left, anl result,right
4719 // and better if result is SFR
4720 if (AOP_TYPE (left) == AOP_ACC)
4721 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4724 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4725 emitcode ("orl", "a,%s",
4726 aopGet (AOP (left), offset, FALSE, FALSE));
4728 aopPut (AOP (result), "a", offset);
4733 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735 freeAsmop (result, NULL, ic, TRUE);
4738 /*-----------------------------------------------------------------*/
4739 /* genXor - code for xclusive or */
4740 /*-----------------------------------------------------------------*/
4742 genXor (iCode * ic, iCode * ifx)
4744 operand *left, *right, *result;
4745 int size, offset = 0;
4746 unsigned long lit = 0L;
4748 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4749 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4750 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4753 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4755 AOP_TYPE (left), AOP_TYPE (right));
4756 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4758 AOP_SIZE (left), AOP_SIZE (right));
4761 /* if left is a literal & right is not ||
4762 if left needs acc & right does not */
4763 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4764 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4766 operand *tmp = right;
4771 /* if result = right then exchange them */
4772 if (sameRegs (AOP (result), AOP (right)))
4774 operand *tmp = right;
4779 /* if right is bit then exchange them */
4780 if (AOP_TYPE (right) == AOP_CRY &&
4781 AOP_TYPE (left) != AOP_CRY)
4783 operand *tmp = right;
4787 if (AOP_TYPE (right) == AOP_LIT)
4788 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4790 size = AOP_SIZE (result);
4794 if (AOP_TYPE (left) == AOP_CRY)
4796 if (AOP_TYPE (right) == AOP_LIT)
4798 // c = bit & literal;
4801 // lit>>1 != 0 => result = 1
4802 if (AOP_TYPE (result) == AOP_CRY)
4805 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4807 continueIfTrue (ifx);
4810 emitcode ("setb", "c");
4817 // lit == 0, result = left
4818 if (size && sameRegs (AOP (result), AOP (left)))
4820 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4824 // lit == 1, result = not(left)
4825 if (size && sameRegs (AOP (result), AOP (left)))
4827 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4832 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4833 emitcode ("cpl", "c");
4842 symbol *tlbl = newiTempLabel (NULL);
4843 if (AOP_TYPE (right) == AOP_CRY)
4846 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4850 int sizer = AOP_SIZE (right);
4852 // if val>>1 != 0, result = 1
4853 emitcode ("setb", "c");
4856 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4858 // test the msb of the lsb
4859 emitcode ("anl", "a,#0xfe");
4860 emitcode ("jnz", "%05d$", tlbl->key + 100);
4864 emitcode ("rrc", "a");
4866 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4867 emitcode ("cpl", "c");
4868 emitcode ("", "%05d$:", (tlbl->key + 100));
4875 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4876 genIfxJump (ifx, "c");
4880 if (sameRegs (AOP (result), AOP (left)))
4882 /* if left is same as result */
4883 for (; size--; offset++)
4885 if (AOP_TYPE (right) == AOP_LIT)
4887 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4889 else if (IS_AOP_PREG (left))
4891 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4892 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4893 aopPut (AOP (result), "a", offset);
4896 emitcode ("xrl", "%s,%s",
4897 aopGet (AOP (left), offset, FALSE, TRUE),
4898 aopGet (AOP (right), offset, FALSE, FALSE));
4902 if (AOP_TYPE (left) == AOP_ACC)
4903 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4907 if (IS_AOP_PREG (left))
4909 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4910 aopPut (AOP (result), "a", offset);
4913 emitcode ("xrl", "%s,a",
4914 aopGet (AOP (left), offset, FALSE, TRUE));
4921 // left & result in different registers
4922 if (AOP_TYPE (result) == AOP_CRY)
4925 // if(size), result in bit
4926 // if(!size && ifx), conditional oper: if(left ^ right)
4927 symbol *tlbl = newiTempLabel (NULL);
4928 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4930 emitcode ("setb", "c");
4933 if ((AOP_TYPE (right) == AOP_LIT) &&
4934 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4936 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4940 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4941 emitcode ("xrl", "a,%s",
4942 aopGet (AOP (left), offset, FALSE, FALSE));
4944 emitcode ("jnz", "%05d$", tlbl->key + 100);
4950 emitcode ("", "%05d$:", tlbl->key + 100);
4954 jmpTrueOrFalse (ifx, tlbl);
4957 for (; (size--); offset++)
4960 // result = left & right
4961 if (AOP_TYPE (right) == AOP_LIT)
4963 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4965 aopPut (AOP (result),
4966 aopGet (AOP (left), offset, FALSE, FALSE),
4971 // faster than result <- left, anl result,right
4972 // and better if result is SFR
4973 if (AOP_TYPE (left) == AOP_ACC)
4974 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("xrl", "a,%s",
4979 aopGet (AOP (left), offset, FALSE, TRUE));
4981 aopPut (AOP (result), "a", offset);
4986 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (result, NULL, ic, TRUE);
4991 /*-----------------------------------------------------------------*/
4992 /* genInline - write the inline code out */
4993 /*-----------------------------------------------------------------*/
4995 genInline (iCode * ic)
4997 char buffer[MAX_INLINEASM];
5001 _G.inLine += (!options.asmpeep);
5002 strcpy (buffer, IC_INLINE (ic));
5004 /* emit each line as a code */
5029 /* emitcode("",buffer); */
5030 _G.inLine -= (!options.asmpeep);
5033 /*-----------------------------------------------------------------*/
5034 /* genRRC - rotate right with carry */
5035 /*-----------------------------------------------------------------*/
5039 operand *left, *result;
5040 int size, offset = 0;
5043 /* rotate right with carry */
5044 left = IC_LEFT (ic);
5045 result = IC_RESULT (ic);
5046 aopOp (left, ic, FALSE);
5047 aopOp (result, ic, FALSE);
5049 /* move it to the result */
5050 size = AOP_SIZE (result);
5055 l = aopGet (AOP (left), offset, FALSE, FALSE);
5057 emitcode ("rrc", "a");
5058 if (AOP_SIZE (result) > 1)
5059 aopPut (AOP (result), "a", offset--);
5061 /* now we need to put the carry into the
5062 highest order byte of the result */
5063 if (AOP_SIZE (result) > 1)
5065 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5068 emitcode ("mov", "acc.7,c");
5069 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5070 freeAsmop (left, NULL, ic, TRUE);
5071 freeAsmop (result, NULL, ic, TRUE);
5074 /*-----------------------------------------------------------------*/
5075 /* genRLC - generate code for rotate left with carry */
5076 /*-----------------------------------------------------------------*/
5080 operand *left, *result;
5081 int size, offset = 0;
5084 /* rotate right with carry */
5085 left = IC_LEFT (ic);
5086 result = IC_RESULT (ic);
5087 aopOp (left, ic, FALSE);
5088 aopOp (result, ic, FALSE);
5090 /* move it to the result */
5091 size = AOP_SIZE (result);
5095 l = aopGet (AOP (left), offset, FALSE, FALSE);
5097 emitcode ("add", "a,acc");
5098 if (AOP_SIZE (result) > 1)
5099 aopPut (AOP (result), "a", offset++);
5102 l = aopGet (AOP (left), offset, FALSE, FALSE);
5104 emitcode ("rlc", "a");
5105 if (AOP_SIZE (result) > 1)
5106 aopPut (AOP (result), "a", offset++);
5109 /* now we need to put the carry into the
5110 highest order byte of the result */
5111 if (AOP_SIZE (result) > 1)
5113 l = aopGet (AOP (result), 0, FALSE, FALSE);
5116 emitcode ("mov", "acc.0,c");
5117 aopPut (AOP (result), "a", 0);
5118 freeAsmop (left, NULL, ic, TRUE);
5119 freeAsmop (result, NULL, ic, TRUE);
5122 /*-----------------------------------------------------------------*/
5123 /* genGetHbit - generates code get highest order bit */
5124 /*-----------------------------------------------------------------*/
5126 genGetHbit (iCode * ic)
5128 operand *left, *result;
5129 left = IC_LEFT (ic);
5130 result = IC_RESULT (ic);
5131 aopOp (left, ic, FALSE);
5132 aopOp (result, ic, FALSE);
5134 /* get the highest order byte into a */
5135 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5136 if (AOP_TYPE (result) == AOP_CRY)
5138 emitcode ("rlc", "a");
5143 emitcode ("rl", "a");
5144 emitcode ("anl", "a,#0x01");
5149 freeAsmop (left, NULL, ic, TRUE);
5150 freeAsmop (result, NULL, ic, TRUE);
5153 /*-----------------------------------------------------------------*/
5154 /* AccRol - rotate left accumulator by known count */
5155 /*-----------------------------------------------------------------*/
5157 AccRol (int shCount)
5159 shCount &= 0x0007; // shCount : 0..7
5166 emitcode ("rl", "a");
5169 emitcode ("rl", "a");
5170 emitcode ("rl", "a");
5173 emitcode ("swap", "a");
5174 emitcode ("rr", "a");
5177 emitcode ("swap", "a");
5180 emitcode ("swap", "a");
5181 emitcode ("rl", "a");
5184 emitcode ("rr", "a");
5185 emitcode ("rr", "a");
5188 emitcode ("rr", "a");
5193 /*-----------------------------------------------------------------*/
5194 /* AccLsh - left shift accumulator by known count */
5195 /*-----------------------------------------------------------------*/
5197 AccLsh (int shCount)
5202 emitcode ("add", "a,acc");
5203 else if (shCount == 2)
5205 emitcode ("add", "a,acc");
5206 emitcode ("add", "a,acc");
5210 /* rotate left accumulator */
5212 /* and kill the lower order bits */
5213 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5218 /*-----------------------------------------------------------------*/
5219 /* AccRsh - right shift accumulator by known count */
5220 /*-----------------------------------------------------------------*/
5222 AccRsh (int shCount)
5229 emitcode ("rrc", "a");
5233 /* rotate right accumulator */
5234 AccRol (8 - shCount);
5235 /* and kill the higher order bits */
5236 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5241 /*-----------------------------------------------------------------*/
5242 /* AccSRsh - signed right shift accumulator by known count */
5243 /*-----------------------------------------------------------------*/
5245 AccSRsh (int shCount)
5252 emitcode ("mov", "c,acc.7");
5253 emitcode ("rrc", "a");
5255 else if (shCount == 2)
5257 emitcode ("mov", "c,acc.7");
5258 emitcode ("rrc", "a");
5259 emitcode ("mov", "c,acc.7");
5260 emitcode ("rrc", "a");
5264 tlbl = newiTempLabel (NULL);
5265 /* rotate right accumulator */
5266 AccRol (8 - shCount);
5267 /* and kill the higher order bits */
5268 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5269 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5270 emitcode ("orl", "a,#0x%02x",
5271 (unsigned char) ~SRMask[shCount]);
5272 emitcode ("", "%05d$:", tlbl->key + 100);
5277 /*-----------------------------------------------------------------*/
5278 /* shiftR1Left2Result - shift right one byte from left to result */
5279 /*-----------------------------------------------------------------*/
5281 shiftR1Left2Result (operand * left, int offl,
5282 operand * result, int offr,
5283 int shCount, int sign)
5285 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5286 /* shift right accumulator */
5291 aopPut (AOP (result), "a", offr);
5294 /*-----------------------------------------------------------------*/
5295 /* shiftL1Left2Result - shift left one byte from left to result */
5296 /*-----------------------------------------------------------------*/
5298 shiftL1Left2Result (operand * left, int offl,
5299 operand * result, int offr, int shCount)
5302 l = aopGet (AOP (left), offl, FALSE, FALSE);
5304 /* shift left accumulator */
5306 aopPut (AOP (result), "a", offr);
5309 /*-----------------------------------------------------------------*/
5310 /* movLeft2Result - move byte from left to result */
5311 /*-----------------------------------------------------------------*/
5313 movLeft2Result (operand * left, int offl,
5314 operand * result, int offr, int sign)
5317 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5319 l = aopGet (AOP (left), offl, FALSE, FALSE);
5321 if (*l == '@' && (IS_AOP_PREG (result)))
5323 emitcode ("mov", "a,%s", l);
5324 aopPut (AOP (result), "a", offr);
5329 aopPut (AOP (result), l, offr);
5332 /* MSB sign in acc.7 ! */
5333 if (getDataSize (left) == offl + 1)
5335 emitcode ("mov", "a,%s", l);
5336 aopPut (AOP (result), "a", offr);
5343 /*-----------------------------------------------------------------*/
5344 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5345 /*-----------------------------------------------------------------*/
5349 emitcode ("rrc", "a");
5350 emitcode ("xch", "a,%s", x);
5351 emitcode ("rrc", "a");
5352 emitcode ("xch", "a,%s", x);
5355 /*-----------------------------------------------------------------*/
5356 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5357 /*-----------------------------------------------------------------*/
5361 emitcode ("xch", "a,%s", x);
5362 emitcode ("rlc", "a");
5363 emitcode ("xch", "a,%s", x);
5364 emitcode ("rlc", "a");
5367 /*-----------------------------------------------------------------*/
5368 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5369 /*-----------------------------------------------------------------*/
5373 emitcode ("xch", "a,%s", x);
5374 emitcode ("add", "a,acc");
5375 emitcode ("xch", "a,%s", x);
5376 emitcode ("rlc", "a");
5379 /*-----------------------------------------------------------------*/
5380 /* AccAXLsh - left shift a:x by known count (0..7) */
5381 /*-----------------------------------------------------------------*/
5383 AccAXLsh (char *x, int shCount)
5398 case 5: // AAAAABBB:CCCCCDDD
5400 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5402 emitcode ("anl", "a,#0x%02x",
5403 SLMask[shCount]); // BBB00000:CCCCCDDD
5405 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5407 AccRol (shCount); // DDDCCCCC:BBB00000
5409 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5411 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5413 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5415 emitcode ("anl", "a,#0x%02x",
5416 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5418 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5420 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5423 case 6: // AAAAAABB:CCCCCCDD
5424 emitcode ("anl", "a,#0x%02x",
5425 SRMask[shCount]); // 000000BB:CCCCCCDD
5426 emitcode ("mov", "c,acc.0"); // c = B
5427 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5429 AccAXRrl1 (x); // BCCCCCCD:D000000B
5430 AccAXRrl1 (x); // BBCCCCCC:DD000000
5432 emitcode("rrc","a");
5433 emitcode("xch","a,%s", x);
5434 emitcode("rrc","a");
5435 emitcode("mov","c,acc.0"); //<< get correct bit
5436 emitcode("xch","a,%s", x);
5438 emitcode("rrc","a");
5439 emitcode("xch","a,%s", x);
5440 emitcode("rrc","a");
5441 emitcode("xch","a,%s", x);
5444 case 7: // a:x <<= 7
5446 emitcode ("anl", "a,#0x%02x",
5447 SRMask[shCount]); // 0000000B:CCCCCCCD
5449 emitcode ("mov", "c,acc.0"); // c = B
5451 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5453 AccAXRrl1 (x); // BCCCCCCC:D0000000
5461 /*-----------------------------------------------------------------*/
5462 /* AccAXRsh - right shift a:x known count (0..7) */
5463 /*-----------------------------------------------------------------*/
5465 AccAXRsh (char *x, int shCount)
5473 AccAXRrl1 (x); // 0->a:x
5478 AccAXRrl1 (x); // 0->a:x
5481 AccAXRrl1 (x); // 0->a:x
5486 case 5: // AAAAABBB:CCCCCDDD = a:x
5488 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5490 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5492 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5494 emitcode ("anl", "a,#0x%02x",
5495 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5497 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5499 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5501 emitcode ("anl", "a,#0x%02x",
5502 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5504 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5506 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5508 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5511 case 6: // AABBBBBB:CCDDDDDD
5513 emitcode ("mov", "c,acc.7");
5514 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5516 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5518 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5520 emitcode ("anl", "a,#0x%02x",
5521 SRMask[shCount]); // 000000AA:BBBBBBCC
5524 case 7: // ABBBBBBB:CDDDDDDD
5526 emitcode ("mov", "c,acc.7"); // c = A
5528 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5530 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5532 emitcode ("anl", "a,#0x%02x",
5533 SRMask[shCount]); // 0000000A:BBBBBBBC
5541 /*-----------------------------------------------------------------*/
5542 /* AccAXRshS - right shift signed a:x known count (0..7) */
5543 /*-----------------------------------------------------------------*/
5545 AccAXRshS (char *x, int shCount)
5553 emitcode ("mov", "c,acc.7");
5554 AccAXRrl1 (x); // s->a:x
5558 emitcode ("mov", "c,acc.7");
5559 AccAXRrl1 (x); // s->a:x
5561 emitcode ("mov", "c,acc.7");
5562 AccAXRrl1 (x); // s->a:x
5567 case 5: // AAAAABBB:CCCCCDDD = a:x
5569 tlbl = newiTempLabel (NULL);
5570 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5572 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5574 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5576 emitcode ("anl", "a,#0x%02x",
5577 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5579 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5581 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5583 emitcode ("anl", "a,#0x%02x",
5584 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5586 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5588 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5590 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5592 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5593 emitcode ("orl", "a,#0x%02x",
5594 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5596 emitcode ("", "%05d$:", tlbl->key + 100);
5597 break; // SSSSAAAA:BBBCCCCC
5599 case 6: // AABBBBBB:CCDDDDDD
5601 tlbl = newiTempLabel (NULL);
5602 emitcode ("mov", "c,acc.7");
5603 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5605 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5607 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5609 emitcode ("anl", "a,#0x%02x",
5610 SRMask[shCount]); // 000000AA:BBBBBBCC
5612 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5613 emitcode ("orl", "a,#0x%02x",
5614 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5616 emitcode ("", "%05d$:", tlbl->key + 100);
5618 case 7: // ABBBBBBB:CDDDDDDD
5620 tlbl = newiTempLabel (NULL);
5621 emitcode ("mov", "c,acc.7"); // c = A
5623 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5625 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5627 emitcode ("anl", "a,#0x%02x",
5628 SRMask[shCount]); // 0000000A:BBBBBBBC
5630 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5631 emitcode ("orl", "a,#0x%02x",
5632 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5634 emitcode ("", "%05d$:", tlbl->key + 100);
5641 /*-----------------------------------------------------------------*/
5642 /* shiftL2Left2Result - shift left two bytes from left to result */
5643 /*-----------------------------------------------------------------*/
5645 shiftL2Left2Result (operand * left, int offl,
5646 operand * result, int offr, int shCount)
5648 if (sameRegs (AOP (result), AOP (left)) &&
5649 ((offl + MSB16) == offr))
5651 /* don't crash result[offr] */
5652 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5653 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5657 movLeft2Result (left, offl, result, offr, 0);
5658 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5660 /* ax << shCount (x = lsb(result)) */
5661 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5662 aopPut (AOP (result), "a", offr + MSB16);
5666 /*-----------------------------------------------------------------*/
5667 /* shiftR2Left2Result - shift right two bytes from left to result */
5668 /*-----------------------------------------------------------------*/
5670 shiftR2Left2Result (operand * left, int offl,
5671 operand * result, int offr,
5672 int shCount, int sign)
5674 if (sameRegs (AOP (result), AOP (left)) &&
5675 ((offl + MSB16) == offr))
5677 /* don't crash result[offr] */
5678 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5679 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5683 movLeft2Result (left, offl, result, offr, 0);
5684 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5686 /* a:x >> shCount (x = lsb(result)) */
5688 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5690 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5691 if (getDataSize (result) > 1)
5692 aopPut (AOP (result), "a", offr + MSB16);
5695 /*-----------------------------------------------------------------*/
5696 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5697 /*-----------------------------------------------------------------*/
5699 shiftLLeftOrResult (operand * left, int offl,
5700 operand * result, int offr, int shCount)
5702 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5703 /* shift left accumulator */
5705 /* or with result */
5706 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5707 /* back to result */
5708 aopPut (AOP (result), "a", offr);
5711 /*-----------------------------------------------------------------*/
5712 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5713 /*-----------------------------------------------------------------*/
5715 shiftRLeftOrResult (operand * left, int offl,
5716 operand * result, int offr, int shCount)
5718 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5719 /* shift right accumulator */
5721 /* or with result */
5722 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5723 /* back to result */
5724 aopPut (AOP (result), "a", offr);
5727 /*-----------------------------------------------------------------*/
5728 /* genlshOne - left shift a one byte quantity by known count */
5729 /*-----------------------------------------------------------------*/
5731 genlshOne (operand * result, operand * left, int shCount)
5733 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5736 /*-----------------------------------------------------------------*/
5737 /* genlshTwo - left shift two bytes by known amount != 0 */
5738 /*-----------------------------------------------------------------*/
5740 genlshTwo (operand * result, operand * left, int shCount)
5744 size = getDataSize (result);
5746 /* if shCount >= 8 */
5754 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5756 movLeft2Result (left, LSB, result, MSB16, 0);
5758 aopPut (AOP (result), zero, LSB);
5761 /* 1 <= shCount <= 7 */
5765 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5767 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5771 /*-----------------------------------------------------------------*/
5772 /* shiftLLong - shift left one long from left to result */
5773 /* offl = LSB or MSB16 */
5774 /*-----------------------------------------------------------------*/
5776 shiftLLong (operand * left, operand * result, int offr)
5779 int size = AOP_SIZE (result);
5781 if (size >= LSB + offr)
5783 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5785 emitcode ("add", "a,acc");
5786 if (sameRegs (AOP (left), AOP (result)) &&
5787 size >= MSB16 + offr && offr != LSB)
5788 emitcode ("xch", "a,%s",
5789 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5791 aopPut (AOP (result), "a", LSB + offr);
5794 if (size >= MSB16 + offr)
5796 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5798 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5801 emitcode ("rlc", "a");
5802 if (sameRegs (AOP (left), AOP (result)) &&
5803 size >= MSB24 + offr && offr != LSB)
5804 emitcode ("xch", "a,%s",
5805 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5807 aopPut (AOP (result), "a", MSB16 + offr);
5810 if (size >= MSB24 + offr)
5812 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5814 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5817 emitcode ("rlc", "a");
5818 if (sameRegs (AOP (left), AOP (result)) &&
5819 size >= MSB32 + offr && offr != LSB)
5820 emitcode ("xch", "a,%s",
5821 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5823 aopPut (AOP (result), "a", MSB24 + offr);
5826 if (size > MSB32 + offr)
5828 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5830 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5833 emitcode ("rlc", "a");
5834 aopPut (AOP (result), "a", MSB32 + offr);
5837 aopPut (AOP (result), zero, LSB);
5840 /*-----------------------------------------------------------------*/
5841 /* genlshFour - shift four byte by a known amount != 0 */
5842 /*-----------------------------------------------------------------*/
5844 genlshFour (operand * result, operand * left, int shCount)
5848 size = AOP_SIZE (result);
5850 /* if shifting more that 3 bytes */
5855 /* lowest order of left goes to the highest
5856 order of the destination */
5857 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5859 movLeft2Result (left, LSB, result, MSB32, 0);
5860 aopPut (AOP (result), zero, LSB);
5861 aopPut (AOP (result), zero, MSB16);
5862 aopPut (AOP (result), zero, MSB24);
5866 /* more than two bytes */
5867 else if (shCount >= 16)
5869 /* lower order two bytes goes to higher order two bytes */
5871 /* if some more remaining */
5873 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5876 movLeft2Result (left, MSB16, result, MSB32, 0);
5877 movLeft2Result (left, LSB, result, MSB24, 0);
5879 aopPut (AOP (result), zero, MSB16);
5880 aopPut (AOP (result), zero, LSB);
5884 /* if more than 1 byte */
5885 else if (shCount >= 8)
5887 /* lower order three bytes goes to higher order three bytes */
5892 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5894 movLeft2Result (left, LSB, result, MSB16, 0);
5900 movLeft2Result (left, MSB24, result, MSB32, 0);
5901 movLeft2Result (left, MSB16, result, MSB24, 0);
5902 movLeft2Result (left, LSB, result, MSB16, 0);
5903 aopPut (AOP (result), zero, LSB);
5905 else if (shCount == 1)
5906 shiftLLong (left, result, MSB16);
5909 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5910 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5911 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5912 aopPut (AOP (result), zero, LSB);
5917 /* 1 <= shCount <= 7 */
5918 else if (shCount <= 2)
5920 shiftLLong (left, result, LSB);
5922 shiftLLong (result, result, LSB);
5924 /* 3 <= shCount <= 7, optimize */
5927 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5928 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5929 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5933 /*-----------------------------------------------------------------*/
5934 /* genLeftShiftLiteral - left shifting by known count */
5935 /*-----------------------------------------------------------------*/
5937 genLeftShiftLiteral (operand * left,
5942 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5945 freeAsmop (right, NULL, ic, TRUE);
5947 aopOp (left, ic, FALSE);
5948 aopOp (result, ic, FALSE);
5950 size = getSize (operandType (result));
5953 emitcode ("; shift left ", "result %d, left %d", size,
5957 /* I suppose that the left size >= result size */
5962 movLeft2Result (left, size, result, size, 0);
5966 else if (shCount >= (size * 8))
5968 aopPut (AOP (result), zero, size);
5974 genlshOne (result, left, shCount);
5979 genlshTwo (result, left, shCount);
5983 genlshFour (result, left, shCount);
5987 freeAsmop (left, NULL, ic, TRUE);
5988 freeAsmop (result, NULL, ic, TRUE);
5991 /*-----------------------------------------------------------------*/
5992 /* genLeftShift - generates code for left shifting */
5993 /*-----------------------------------------------------------------*/
5995 genLeftShift (iCode * ic)
5997 operand *left, *right, *result;
6000 symbol *tlbl, *tlbl1;
6002 right = IC_RIGHT (ic);
6003 left = IC_LEFT (ic);
6004 result = IC_RESULT (ic);
6006 aopOp (right, ic, FALSE);
6008 /* if the shift count is known then do it
6009 as efficiently as possible */
6010 if (AOP_TYPE (right) == AOP_LIT)
6012 genLeftShiftLiteral (left, right, result, ic);
6016 /* shift count is unknown then we have to form
6017 a loop get the loop count in B : Note: we take
6018 only the lower order byte since shifting
6019 more that 32 bits make no sense anyway, ( the
6020 largest size of an object can be only 32 bits ) */
6022 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6023 emitcode ("inc", "b");
6024 freeAsmop (right, NULL, ic, TRUE);
6025 aopOp (left, ic, FALSE);
6026 aopOp (result, ic, FALSE);
6028 /* now move the left to the result if they are not the
6030 if (!sameRegs (AOP (left), AOP (result)) &&
6031 AOP_SIZE (result) > 1)
6034 size = AOP_SIZE (result);
6038 l = aopGet (AOP (left), offset, FALSE, TRUE);
6039 if (*l == '@' && (IS_AOP_PREG (result)))
6042 emitcode ("mov", "a,%s", l);
6043 aopPut (AOP (result), "a", offset);
6046 aopPut (AOP (result), l, offset);
6051 tlbl = newiTempLabel (NULL);
6052 size = AOP_SIZE (result);
6054 tlbl1 = newiTempLabel (NULL);
6056 /* if it is only one byte then */
6059 symbol *tlbl1 = newiTempLabel (NULL);
6061 l = aopGet (AOP (left), 0, FALSE, FALSE);
6063 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6064 emitcode ("", "%05d$:", tlbl->key + 100);
6065 emitcode ("add", "a,acc");
6066 emitcode ("", "%05d$:", tlbl1->key + 100);
6067 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6068 aopPut (AOP (result), "a", 0);
6072 reAdjustPreg (AOP (result));
6074 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6075 emitcode ("", "%05d$:", tlbl->key + 100);
6076 l = aopGet (AOP (result), offset, FALSE, FALSE);
6078 emitcode ("add", "a,acc");
6079 aopPut (AOP (result), "a", offset++);
6082 l = aopGet (AOP (result), offset, FALSE, FALSE);
6084 emitcode ("rlc", "a");
6085 aopPut (AOP (result), "a", offset++);
6087 reAdjustPreg (AOP (result));
6089 emitcode ("", "%05d$:", tlbl1->key + 100);
6090 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6092 freeAsmop (left, NULL, ic, TRUE);
6093 freeAsmop (result, NULL, ic, TRUE);
6096 /*-----------------------------------------------------------------*/
6097 /* genrshOne - right shift a one byte quantity by known count */
6098 /*-----------------------------------------------------------------*/
6100 genrshOne (operand * result, operand * left,
6101 int shCount, int sign)
6103 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6106 /*-----------------------------------------------------------------*/
6107 /* genrshTwo - right shift two bytes by known amount != 0 */
6108 /*-----------------------------------------------------------------*/
6110 genrshTwo (operand * result, operand * left,
6111 int shCount, int sign)
6113 /* if shCount >= 8 */
6118 shiftR1Left2Result (left, MSB16, result, LSB,
6121 movLeft2Result (left, MSB16, result, LSB, sign);
6122 addSign (result, MSB16, sign);
6125 /* 1 <= shCount <= 7 */
6127 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6130 /*-----------------------------------------------------------------*/
6131 /* shiftRLong - shift right one long from left to result */
6132 /* offl = LSB or MSB16 */
6133 /*-----------------------------------------------------------------*/
6135 shiftRLong (operand * left, int offl,
6136 operand * result, int sign)
6139 emitcode ("clr", "c");
6140 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6142 emitcode ("mov", "c,acc.7");
6143 emitcode ("rrc", "a");
6144 aopPut (AOP (result), "a", MSB32 - offl);
6146 /* add sign of "a" */
6147 addSign (result, MSB32, sign);
6149 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6150 emitcode ("rrc", "a");
6151 aopPut (AOP (result), "a", MSB24 - offl);
6153 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6154 emitcode ("rrc", "a");
6155 aopPut (AOP (result), "a", MSB16 - offl);
6159 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6160 emitcode ("rrc", "a");
6161 aopPut (AOP (result), "a", LSB);
6165 /*-----------------------------------------------------------------*/
6166 /* genrshFour - shift four byte by a known amount != 0 */
6167 /*-----------------------------------------------------------------*/
6169 genrshFour (operand * result, operand * left,
6170 int shCount, int sign)
6172 /* if shifting more that 3 bytes */
6177 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6179 movLeft2Result (left, MSB32, result, LSB, sign);
6180 addSign (result, MSB16, sign);
6182 else if (shCount >= 16)
6186 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6189 movLeft2Result (left, MSB24, result, LSB, 0);
6190 movLeft2Result (left, MSB32, result, MSB16, sign);
6192 addSign (result, MSB24, sign);
6194 else if (shCount >= 8)
6198 shiftRLong (left, MSB16, result, sign);
6199 else if (shCount == 0)
6201 movLeft2Result (left, MSB16, result, LSB, 0);
6202 movLeft2Result (left, MSB24, result, MSB16, 0);
6203 movLeft2Result (left, MSB32, result, MSB24, sign);
6204 addSign (result, MSB32, sign);
6208 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6209 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6210 /* the last shift is signed */
6211 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6212 addSign (result, MSB32, sign);
6216 { /* 1 <= shCount <= 7 */
6219 shiftRLong (left, LSB, result, sign);
6221 shiftRLong (result, LSB, result, sign);
6225 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6226 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6227 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6232 /*-----------------------------------------------------------------*/
6233 /* genRightShiftLiteral - right shifting by known count */
6234 /*-----------------------------------------------------------------*/
6236 genRightShiftLiteral (operand * left,
6242 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6245 freeAsmop (right, NULL, ic, TRUE);
6247 aopOp (left, ic, FALSE);
6248 aopOp (result, ic, FALSE);
6251 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6255 size = getDataSize (left);
6256 /* test the LEFT size !!! */
6258 /* I suppose that the left size >= result size */
6261 size = getDataSize (result);
6263 movLeft2Result (left, size, result, size, 0);
6266 else if (shCount >= (size * 8))
6269 /* get sign in acc.7 */
6270 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6271 addSign (result, LSB, sign);
6278 genrshOne (result, left, shCount, sign);
6282 genrshTwo (result, left, shCount, sign);
6286 genrshFour (result, left, shCount, sign);
6292 freeAsmop (left, NULL, ic, TRUE);
6293 freeAsmop (result, NULL, ic, TRUE);
6297 /*-----------------------------------------------------------------*/
6298 /* genSignedRightShift - right shift of signed number */
6299 /*-----------------------------------------------------------------*/
6301 genSignedRightShift (iCode * ic)
6303 operand *right, *left, *result;
6306 symbol *tlbl, *tlbl1;
6308 /* we do it the hard way put the shift count in b
6309 and loop thru preserving the sign */
6311 right = IC_RIGHT (ic);
6312 left = IC_LEFT (ic);
6313 result = IC_RESULT (ic);
6315 aopOp (right, ic, FALSE);
6318 if (AOP_TYPE (right) == AOP_LIT)
6320 genRightShiftLiteral (left, right, result, ic, 1);
6323 /* shift count is unknown then we have to form
6324 a loop get the loop count in B : Note: we take
6325 only the lower order byte since shifting
6326 more that 32 bits make no sense anyway, ( the
6327 largest size of an object can be only 32 bits ) */
6329 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6330 emitcode ("inc", "b");
6331 freeAsmop (right, NULL, ic, TRUE);
6332 aopOp (left, ic, FALSE);
6333 aopOp (result, ic, FALSE);
6335 /* now move the left to the result if they are not the
6337 if (!sameRegs (AOP (left), AOP (result)) &&
6338 AOP_SIZE (result) > 1)
6341 size = AOP_SIZE (result);
6345 l = aopGet (AOP (left), offset, FALSE, TRUE);
6346 if (*l == '@' && IS_AOP_PREG (result))
6349 emitcode ("mov", "a,%s", l);
6350 aopPut (AOP (result), "a", offset);
6353 aopPut (AOP (result), l, offset);
6358 /* mov the highest order bit to OVR */
6359 tlbl = newiTempLabel (NULL);
6360 tlbl1 = newiTempLabel (NULL);
6362 size = AOP_SIZE (result);
6364 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6365 emitcode ("rlc", "a");
6366 emitcode ("mov", "ov,c");
6367 /* if it is only one byte then */
6370 l = aopGet (AOP (left), 0, FALSE, FALSE);
6372 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6373 emitcode ("", "%05d$:", tlbl->key + 100);
6374 emitcode ("mov", "c,ov");
6375 emitcode ("rrc", "a");
6376 emitcode ("", "%05d$:", tlbl1->key + 100);
6377 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6378 aopPut (AOP (result), "a", 0);
6382 reAdjustPreg (AOP (result));
6383 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6384 emitcode ("", "%05d$:", tlbl->key + 100);
6385 emitcode ("mov", "c,ov");
6388 l = aopGet (AOP (result), offset, FALSE, FALSE);
6390 emitcode ("rrc", "a");
6391 aopPut (AOP (result), "a", offset--);
6393 reAdjustPreg (AOP (result));
6394 emitcode ("", "%05d$:", tlbl1->key + 100);
6395 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6398 freeAsmop (left, NULL, ic, TRUE);
6399 freeAsmop (result, NULL, ic, TRUE);
6402 /*-----------------------------------------------------------------*/
6403 /* genRightShift - generate code for right shifting */
6404 /*-----------------------------------------------------------------*/
6406 genRightShift (iCode * ic)
6408 operand *right, *left, *result;
6412 symbol *tlbl, *tlbl1;
6414 /* if signed then we do it the hard way preserve the
6415 sign bit moving it inwards */
6416 retype = getSpec (operandType (IC_RESULT (ic)));
6418 if (!SPEC_USIGN (retype))
6420 genSignedRightShift (ic);
6424 /* signed & unsigned types are treated the same : i.e. the
6425 signed is NOT propagated inwards : quoting from the
6426 ANSI - standard : "for E1 >> E2, is equivalent to division
6427 by 2**E2 if unsigned or if it has a non-negative value,
6428 otherwise the result is implementation defined ", MY definition
6429 is that the sign does not get propagated */
6431 right = IC_RIGHT (ic);
6432 left = IC_LEFT (ic);
6433 result = IC_RESULT (ic);
6435 aopOp (right, ic, FALSE);
6437 /* if the shift count is known then do it
6438 as efficiently as possible */
6439 if (AOP_TYPE (right) == AOP_LIT)
6441 genRightShiftLiteral (left, right, result, ic, 0);
6445 /* shift count is unknown then we have to form
6446 a loop get the loop count in B : Note: we take
6447 only the lower order byte since shifting
6448 more that 32 bits make no sense anyway, ( the
6449 largest size of an object can be only 32 bits ) */
6451 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6452 emitcode ("inc", "b");
6453 freeAsmop (right, NULL, ic, TRUE);
6454 aopOp (left, ic, FALSE);
6455 aopOp (result, ic, FALSE);
6457 /* now move the left to the result if they are not the
6459 if (!sameRegs (AOP (left), AOP (result)) &&
6460 AOP_SIZE (result) > 1)
6463 size = AOP_SIZE (result);
6467 l = aopGet (AOP (left), offset, FALSE, TRUE);
6468 if (*l == '@' && IS_AOP_PREG (result))
6471 emitcode ("mov", "a,%s", l);
6472 aopPut (AOP (result), "a", offset);
6475 aopPut (AOP (result), l, offset);
6480 tlbl = newiTempLabel (NULL);
6481 tlbl1 = newiTempLabel (NULL);
6482 size = AOP_SIZE (result);
6485 /* if it is only one byte then */
6488 l = aopGet (AOP (left), 0, FALSE, FALSE);
6490 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6491 emitcode ("", "%05d$:", tlbl->key + 100);
6493 emitcode ("rrc", "a");
6494 emitcode ("", "%05d$:", tlbl1->key + 100);
6495 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6496 aopPut (AOP (result), "a", 0);
6500 reAdjustPreg (AOP (result));
6501 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6502 emitcode ("", "%05d$:", tlbl->key + 100);
6506 l = aopGet (AOP (result), offset, FALSE, FALSE);
6508 emitcode ("rrc", "a");
6509 aopPut (AOP (result), "a", offset--);
6511 reAdjustPreg (AOP (result));
6513 emitcode ("", "%05d$:", tlbl1->key + 100);
6514 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6517 freeAsmop (left, NULL, ic, TRUE);
6518 freeAsmop (result, NULL, ic, TRUE);
6521 /*-----------------------------------------------------------------*/
6522 /* genUnpackBits - generates code for unpacking bits */
6523 /*-----------------------------------------------------------------*/
6525 genUnpackBits (operand * result, char *rname, int ptype)
6533 etype = getSpec (operandType (result));
6534 rsize = getSize (operandType (result));
6535 /* read the first byte */
6541 emitcode ("mov", "a,@%s", rname);
6545 emitcode ("movx", "a,@%s", rname);
6549 emitcode ("movx", "a,@dptr");
6553 emitcode ("clr", "a");
6554 emitcode ("movc", "a,%s", "@a+dptr");
6558 emitcode ("lcall", "__gptrget");
6562 rlen = SPEC_BLEN (etype);
6564 /* if we have bitdisplacement then it fits */
6565 /* into this byte completely or if length is */
6566 /* less than a byte */
6567 if ((shCnt = SPEC_BSTR (etype)) ||
6568 (SPEC_BLEN (etype) <= 8))
6571 /* shift right acc */
6574 emitcode ("anl", "a,#0x%02x",
6575 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6576 aopPut (AOP (result), "a", offset++);
6580 /* bit field did not fit in a byte */
6581 aopPut (AOP (result), "a", offset++);
6590 emitcode ("inc", "%s", rname);
6591 emitcode ("mov", "a,@%s", rname);
6595 emitcode ("inc", "%s", rname);
6596 emitcode ("movx", "a,@%s", rname);
6600 emitcode ("inc", "dptr");
6601 emitcode ("movx", "a,@dptr");
6605 emitcode ("clr", "a");
6606 emitcode ("inc", "dptr");
6607 emitcode ("movc", "a", "@a+dptr");
6611 emitcode ("inc", "dptr");
6612 emitcode ("lcall", "__gptrget");
6617 /* if we are done */
6621 aopPut (AOP (result), "a", offset++);
6627 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6629 aopPut (AOP (result), "a", offset++);
6637 aopPut (AOP (result), zero, offset++);
6643 /*-----------------------------------------------------------------*/
6644 /* genDataPointerGet - generates code when ptr offset is known */
6645 /*-----------------------------------------------------------------*/
6647 genDataPointerGet (operand * left,
6653 int size, offset = 0;
6654 aopOp (result, ic, TRUE);
6656 /* get the string representation of the name */
6657 l = aopGet (AOP (left), 0, FALSE, TRUE);
6658 size = AOP_SIZE (result);
6662 sprintf (buffer, "(%s + %d)", l + 1, offset);
6664 sprintf (buffer, "%s", l + 1);
6665 aopPut (AOP (result), buffer, offset++);
6668 freeAsmop (left, NULL, ic, TRUE);
6669 freeAsmop (result, NULL, ic, TRUE);
6672 /*-----------------------------------------------------------------*/
6673 /* genNearPointerGet - emitcode for near pointer fetch */
6674 /*-----------------------------------------------------------------*/
6676 genNearPointerGet (operand * left,
6684 sym_link *rtype, *retype;
6685 sym_link *ltype = operandType (left);
6688 rtype = operandType (result);
6689 retype = getSpec (rtype);
6691 aopOp (left, ic, FALSE);
6693 /* if left is rematerialisable and
6694 result is not bit variable type and
6695 the left is pointer to data space i.e
6696 lower 128 bytes of space */
6697 if (AOP_TYPE (left) == AOP_IMMD &&
6698 !IS_BITVAR (retype) &&
6699 DCL_TYPE (ltype) == POINTER)
6701 genDataPointerGet (left, result, ic);
6705 /* if the value is already in a pointer register
6706 then don't need anything more */
6707 if (!AOP_INPREG (AOP (left)))
6709 /* otherwise get a free pointer register */
6711 preg = getFreePtr (ic, &aop, FALSE);
6712 emitcode ("mov", "%s,%s",
6714 aopGet (AOP (left), 0, FALSE, TRUE));
6718 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6720 aopOp (result, ic, FALSE);
6722 /* if bitfield then unpack the bits */
6723 if (IS_BITVAR (retype))
6724 genUnpackBits (result, rname, POINTER);
6727 /* we have can just get the values */
6728 int size = AOP_SIZE (result);
6733 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6736 emitcode ("mov", "a,@%s", rname);
6737 aopPut (AOP (result), "a", offset);
6741 sprintf (buffer, "@%s", rname);
6742 aopPut (AOP (result), buffer, offset);
6746 emitcode ("inc", "%s", rname);
6750 /* now some housekeeping stuff */
6751 if (aop) /* we had to allocate for this iCode */
6753 if (pi) { /* post increment present */
6754 aopPut(AOP ( left ),rname,0);
6756 freeAsmop (NULL, aop, ic, TRUE);
6760 /* we did not allocate which means left
6761 already in a pointer register, then
6762 if size > 0 && this could be used again
6763 we have to point it back to where it
6765 if ((AOP_SIZE (result) > 1 &&
6766 !OP_SYMBOL (left)->remat &&
6767 (OP_SYMBOL (left)->liveTo > ic->seq ||
6771 int size = AOP_SIZE (result) - 1;
6773 emitcode ("dec", "%s", rname);
6778 freeAsmop (left, NULL, ic, TRUE);
6779 freeAsmop (result, NULL, ic, TRUE);
6780 if (pi) pi->generated = 1;
6783 /*-----------------------------------------------------------------*/
6784 /* genPagedPointerGet - emitcode for paged pointer fetch */
6785 /*-----------------------------------------------------------------*/
6787 genPagedPointerGet (operand * left,
6795 sym_link *rtype, *retype;
6797 rtype = operandType (result);
6798 retype = getSpec (rtype);
6800 aopOp (left, ic, FALSE);
6802 /* if the value is already in a pointer register
6803 then don't need anything more */
6804 if (!AOP_INPREG (AOP (left)))
6806 /* otherwise get a free pointer register */
6808 preg = getFreePtr (ic, &aop, FALSE);
6809 emitcode ("mov", "%s,%s",
6811 aopGet (AOP (left), 0, FALSE, TRUE));
6815 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6817 aopOp (result, ic, FALSE);
6819 /* if bitfield then unpack the bits */
6820 if (IS_BITVAR (retype))
6821 genUnpackBits (result, rname, PPOINTER);
6824 /* we have can just get the values */
6825 int size = AOP_SIZE (result);
6831 emitcode ("movx", "a,@%s", rname);
6832 aopPut (AOP (result), "a", offset);
6837 emitcode ("inc", "%s", rname);
6841 /* now some housekeeping stuff */
6842 if (aop) /* we had to allocate for this iCode */
6844 if (pi) aopPut ( AOP (left), rname, 0);
6845 freeAsmop (NULL, aop, ic, TRUE);
6849 /* we did not allocate which means left
6850 already in a pointer register, then
6851 if size > 0 && this could be used again
6852 we have to point it back to where it
6854 if ((AOP_SIZE (result) > 1 &&
6855 !OP_SYMBOL (left)->remat &&
6856 (OP_SYMBOL (left)->liveTo > ic->seq ||
6860 int size = AOP_SIZE (result) - 1;
6862 emitcode ("dec", "%s", rname);
6867 freeAsmop (left, NULL, ic, TRUE);
6868 freeAsmop (result, NULL, ic, TRUE);
6869 if (pi) pi->generated = 1;
6873 /*-----------------------------------------------------------------*/
6874 /* genFarPointerGet - gget value from far space */
6875 /*-----------------------------------------------------------------*/
6877 genFarPointerGet (operand * left,
6878 operand * result, iCode * ic, iCode * pi)
6881 sym_link *retype = getSpec (operandType (result));
6883 aopOp (left, ic, FALSE);
6885 /* if the operand is already in dptr
6886 then we do nothing else we move the value to dptr */
6887 if (AOP_TYPE (left) != AOP_STR)
6889 /* if this is remateriazable */
6890 if (AOP_TYPE (left) == AOP_IMMD)
6891 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6893 { /* we need to get it byte by byte */
6894 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6895 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6898 /* so dptr know contains the address */
6899 aopOp (result, ic, FALSE);
6901 /* if bit then unpack */
6902 if (IS_BITVAR (retype))
6903 genUnpackBits (result, "dptr", FPOINTER);
6906 size = AOP_SIZE (result);
6911 emitcode ("movx", "a,@dptr");
6912 aopPut (AOP (result), "a", offset++);
6914 emitcode ("inc", "dptr");
6918 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6919 aopPut ( AOP (left), "dpl", 0);
6920 aopPut ( AOP (left), "dph", 1);
6923 freeAsmop (left, NULL, ic, TRUE);
6924 freeAsmop (result, NULL, ic, TRUE);
6927 /*-----------------------------------------------------------------*/
6928 /* genCodePointerGet - gget value from code space */
6929 /*-----------------------------------------------------------------*/
6931 genCodePointerGet (operand * left,
6932 operand * result, iCode * ic, iCode *pi)
6935 sym_link *retype = getSpec (operandType (result));
6937 aopOp (left, ic, FALSE);
6939 /* if the operand is already in dptr
6940 then we do nothing else we move the value to dptr */
6941 if (AOP_TYPE (left) != AOP_STR)
6943 /* if this is remateriazable */
6944 if (AOP_TYPE (left) == AOP_IMMD)
6945 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6947 { /* we need to get it byte by byte */
6948 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6949 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6952 /* so dptr know contains the address */
6953 aopOp (result, ic, FALSE);
6955 /* if bit then unpack */
6956 if (IS_BITVAR (retype))
6957 genUnpackBits (result, "dptr", CPOINTER);
6960 size = AOP_SIZE (result);
6965 emitcode ("clr", "a");
6966 emitcode ("movc", "a,@a+dptr");
6967 aopPut (AOP (result), "a", offset++);
6969 emitcode ("inc", "dptr");
6973 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6974 aopPut ( AOP (left), "dpl", 0);
6975 aopPut ( AOP (left), "dph", 1);
6978 freeAsmop (left, NULL, ic, TRUE);
6979 freeAsmop (result, NULL, ic, TRUE);
6982 /*-----------------------------------------------------------------*/
6983 /* genGenPointerGet - gget value from generic pointer space */
6984 /*-----------------------------------------------------------------*/
6986 genGenPointerGet (operand * left,
6987 operand * result, iCode * ic, iCode *pi)
6990 sym_link *retype = getSpec (operandType (result));
6992 aopOp (left, ic, FALSE);
6994 /* if the operand is already in dptr
6995 then we do nothing else we move the value to dptr */
6996 if (AOP_TYPE (left) != AOP_STR)
6998 /* if this is remateriazable */
6999 if (AOP_TYPE (left) == AOP_IMMD)
7001 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7002 emitcode ("mov", "b,#%d", pointerCode (retype));
7005 { /* we need to get it byte by byte */
7006 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7007 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7008 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7011 /* so dptr know contains the address */
7012 aopOp (result, ic, FALSE);
7014 /* if bit then unpack */
7015 if (IS_BITVAR (retype))
7016 genUnpackBits (result, "dptr", GPOINTER);
7019 size = AOP_SIZE (result);
7024 emitcode ("lcall", "__gptrget");
7025 aopPut (AOP (result), "a", offset++);
7027 emitcode ("inc", "dptr");
7031 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7032 aopPut ( AOP (left), "dpl", 0);
7033 aopPut ( AOP (left), "dph", 1);
7036 freeAsmop (left, NULL, ic, TRUE);
7037 freeAsmop (result, NULL, ic, TRUE);
7040 /*-----------------------------------------------------------------*/
7041 /* genPointerGet - generate code for pointer get */
7042 /*-----------------------------------------------------------------*/
7044 genPointerGet (iCode * ic, iCode *pi)
7046 operand *left, *result;
7047 sym_link *type, *etype;
7050 left = IC_LEFT (ic);
7051 result = IC_RESULT (ic);
7053 /* depending on the type of pointer we need to
7054 move it to the correct pointer register */
7055 type = operandType (left);
7056 etype = getSpec (type);
7057 /* if left is of type of pointer then it is simple */
7058 if (IS_PTR (type) && !IS_FUNC (type->next))
7059 p_type = DCL_TYPE (type);
7062 /* we have to go by the storage class */
7063 p_type = PTR_TYPE (SPEC_OCLS (etype));
7066 /* now that we have the pointer type we assign
7067 the pointer values */
7073 genNearPointerGet (left, result, ic, pi);
7077 genPagedPointerGet (left, result, ic, pi);
7081 genFarPointerGet (left, result, ic, pi);
7085 genCodePointerGet (left, result, ic, pi);
7089 genGenPointerGet (left, result, ic, pi);
7095 /*-----------------------------------------------------------------*/
7096 /* genPackBits - generates code for packed bit storage */
7097 /*-----------------------------------------------------------------*/
7099 genPackBits (sym_link * etype,
7101 char *rname, int p_type)
7109 blen = SPEC_BLEN (etype);
7110 bstr = SPEC_BSTR (etype);
7112 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7115 /* if the bit lenth is less than or */
7116 /* it exactly fits a byte then */
7117 if (SPEC_BLEN (etype) <= 8)
7119 shCount = SPEC_BSTR (etype);
7121 /* shift left acc */
7124 if (SPEC_BLEN (etype) < 8)
7125 { /* if smaller than a byte */
7131 emitcode ("mov", "b,a");
7132 emitcode ("mov", "a,@%s", rname);
7136 emitcode ("mov", "b,a");
7137 emitcode ("movx", "a,@dptr");
7141 emitcode ("push", "b");
7142 emitcode ("push", "acc");
7143 emitcode ("lcall", "__gptrget");
7144 emitcode ("pop", "b");
7148 emitcode ("anl", "a,#0x%02x", (unsigned char)
7149 ((unsigned char) (0xFF << (blen + bstr)) |
7150 (unsigned char) (0xFF >> (8 - bstr))));
7151 emitcode ("orl", "a,b");
7152 if (p_type == GPOINTER)
7153 emitcode ("pop", "b");
7160 emitcode ("mov", "@%s,a", rname);
7164 emitcode ("movx", "@dptr,a");
7168 emitcode ("lcall", "__gptrput");
7173 if (SPEC_BLEN (etype) <= 8)
7176 emitcode ("inc", "%s", rname);
7177 rLen = SPEC_BLEN (etype);
7179 /* now generate for lengths greater than one byte */
7183 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7195 emitcode ("mov", "@%s,a", rname);
7198 emitcode ("mov", "@%s,%s", rname, l);
7203 emitcode ("movx", "@dptr,a");
7208 emitcode ("lcall", "__gptrput");
7211 emitcode ("inc", "%s", rname);
7216 /* last last was not complete */
7219 /* save the byte & read byte */
7223 emitcode ("mov", "b,a");
7224 emitcode ("mov", "a,@%s", rname);
7228 emitcode ("mov", "b,a");
7229 emitcode ("movx", "a,@dptr");
7233 emitcode ("push", "b");
7234 emitcode ("push", "acc");
7235 emitcode ("lcall", "__gptrget");
7236 emitcode ("pop", "b");
7240 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7241 emitcode ("orl", "a,b");
7244 if (p_type == GPOINTER)
7245 emitcode ("pop", "b");
7251 emitcode ("mov", "@%s,a", rname);
7255 emitcode ("movx", "@dptr,a");
7259 emitcode ("lcall", "__gptrput");
7263 /*-----------------------------------------------------------------*/
7264 /* genDataPointerSet - remat pointer to data space */
7265 /*-----------------------------------------------------------------*/
7267 genDataPointerSet (operand * right,
7271 int size, offset = 0;
7272 char *l, buffer[256];
7274 aopOp (right, ic, FALSE);
7276 l = aopGet (AOP (result), 0, FALSE, TRUE);
7277 size = AOP_SIZE (right);
7281 sprintf (buffer, "(%s + %d)", l + 1, offset);
7283 sprintf (buffer, "%s", l + 1);
7284 emitcode ("mov", "%s,%s", buffer,
7285 aopGet (AOP (right), offset++, FALSE, FALSE));
7288 freeAsmop (right, NULL, ic, TRUE);
7289 freeAsmop (result, NULL, ic, TRUE);
7292 /*-----------------------------------------------------------------*/
7293 /* genNearPointerSet - emitcode for near pointer put */
7294 /*-----------------------------------------------------------------*/
7296 genNearPointerSet (operand * right,
7304 sym_link *retype, *letype;
7305 sym_link *ptype = operandType (result);
7307 retype = getSpec (operandType (right));
7308 letype = getSpec (ptype);
7309 aopOp (result, ic, FALSE);
7311 /* if the result is rematerializable &
7312 in data space & not a bit variable */
7313 if (AOP_TYPE (result) == AOP_IMMD &&
7314 DCL_TYPE (ptype) == POINTER &&
7315 !IS_BITVAR (retype) &&
7316 !IS_BITVAR (letype))
7318 genDataPointerSet (right, result, ic);
7322 /* if the value is already in a pointer register
7323 then don't need anything more */
7324 if (!AOP_INPREG (AOP (result)))
7326 /* otherwise get a free pointer register */
7328 preg = getFreePtr (ic, &aop, FALSE);
7329 emitcode ("mov", "%s,%s",
7331 aopGet (AOP (result), 0, FALSE, TRUE));
7335 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7337 aopOp (right, ic, FALSE);
7339 /* if bitfield then unpack the bits */
7340 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7341 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7344 /* we have can just get the values */
7345 int size = AOP_SIZE (right);
7350 l = aopGet (AOP (right), offset, FALSE, TRUE);
7354 emitcode ("mov", "@%s,a", rname);
7357 emitcode ("mov", "@%s,%s", rname, l);
7359 emitcode ("inc", "%s", rname);
7364 /* now some housekeeping stuff */
7365 if (aop) /* we had to allocate for this iCode */
7367 if (pi) aopPut (AOP (result),rname,0);
7368 freeAsmop (NULL, aop, ic, TRUE);
7372 /* we did not allocate which means left
7373 already in a pointer register, then
7374 if size > 0 && this could be used again
7375 we have to point it back to where it
7377 if ((AOP_SIZE (right) > 1 &&
7378 !OP_SYMBOL (result)->remat &&
7379 (OP_SYMBOL (result)->liveTo > ic->seq ||
7383 int size = AOP_SIZE (right) - 1;
7385 emitcode ("dec", "%s", rname);
7390 if (pi) pi->generated = 1;
7391 freeAsmop (result, NULL, ic, TRUE);
7392 freeAsmop (right, NULL, ic, TRUE);
7395 /*-----------------------------------------------------------------*/
7396 /* genPagedPointerSet - emitcode for Paged pointer put */
7397 /*-----------------------------------------------------------------*/
7399 genPagedPointerSet (operand * right,
7407 sym_link *retype, *letype;
7409 retype = getSpec (operandType (right));
7410 letype = getSpec (operandType (result));
7412 aopOp (result, ic, FALSE);
7414 /* if the value is already in a pointer register
7415 then don't need anything more */
7416 if (!AOP_INPREG (AOP (result)))
7418 /* otherwise get a free pointer register */
7420 preg = getFreePtr (ic, &aop, FALSE);
7421 emitcode ("mov", "%s,%s",
7423 aopGet (AOP (result), 0, FALSE, TRUE));
7427 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7429 aopOp (right, ic, FALSE);
7431 /* if bitfield then unpack the bits */
7432 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7433 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7436 /* we have can just get the values */
7437 int size = AOP_SIZE (right);
7442 l = aopGet (AOP (right), offset, FALSE, TRUE);
7445 emitcode ("movx", "@%s,a", rname);
7448 emitcode ("inc", "%s", rname);
7454 /* now some housekeeping stuff */
7455 if (aop) /* we had to allocate for this iCode */
7457 if (pi) aopPut (AOP (result),rname,0);
7458 freeAsmop (NULL, aop, ic, TRUE);
7462 /* we did not allocate which means left
7463 already in a pointer register, then
7464 if size > 0 && this could be used again
7465 we have to point it back to where it
7467 if (AOP_SIZE (right) > 1 &&
7468 !OP_SYMBOL (result)->remat &&
7469 (OP_SYMBOL (result)->liveTo > ic->seq ||
7472 int size = AOP_SIZE (right) - 1;
7474 emitcode ("dec", "%s", rname);
7479 if (pi) pi->generated = 1;
7480 freeAsmop (result, NULL, ic, TRUE);
7481 freeAsmop (right, NULL, ic, TRUE);
7486 /*-----------------------------------------------------------------*/
7487 /* genFarPointerSet - set value from far space */
7488 /*-----------------------------------------------------------------*/
7490 genFarPointerSet (operand * right,
7491 operand * result, iCode * ic, iCode * pi)
7494 sym_link *retype = getSpec (operandType (right));
7495 sym_link *letype = getSpec (operandType (result));
7496 aopOp (result, ic, FALSE);
7498 /* if the operand is already in dptr
7499 then we do nothing else we move the value to dptr */
7500 if (AOP_TYPE (result) != AOP_STR)
7502 /* if this is remateriazable */
7503 if (AOP_TYPE (result) == AOP_IMMD)
7504 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7506 { /* we need to get it byte by byte */
7507 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7508 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7511 /* so dptr know contains the address */
7512 aopOp (right, ic, FALSE);
7514 /* if bit then unpack */
7515 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7516 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7519 size = AOP_SIZE (right);
7524 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7526 emitcode ("movx", "@dptr,a");
7528 emitcode ("inc", "dptr");
7531 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7532 aopPut (AOP(result),"dpl",0);
7533 aopPut (AOP(result),"dph",1);
7536 freeAsmop (result, NULL, ic, TRUE);
7537 freeAsmop (right, NULL, ic, TRUE);
7540 /*-----------------------------------------------------------------*/
7541 /* genGenPointerSet - set value from generic pointer space */
7542 /*-----------------------------------------------------------------*/
7544 genGenPointerSet (operand * right,
7545 operand * result, iCode * ic, iCode * pi)
7548 sym_link *retype = getSpec (operandType (right));
7549 sym_link *letype = getSpec (operandType (result));
7551 aopOp (result, ic, FALSE);
7553 /* if the operand is already in dptr
7554 then we do nothing else we move the value to dptr */
7555 if (AOP_TYPE (result) != AOP_STR)
7557 /* if this is remateriazable */
7558 if (AOP_TYPE (result) == AOP_IMMD)
7560 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7561 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7564 { /* we need to get it byte by byte */
7565 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7566 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7567 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7570 /* so dptr know contains the address */
7571 aopOp (right, ic, FALSE);
7573 /* if bit then unpack */
7574 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7575 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7578 size = AOP_SIZE (right);
7583 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7585 emitcode ("lcall", "__gptrput");
7587 emitcode ("inc", "dptr");
7591 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7592 aopPut (AOP(result),"dpl",0);
7593 aopPut (AOP(result),"dph",1);
7596 freeAsmop (result, NULL, ic, TRUE);
7597 freeAsmop (right, NULL, ic, TRUE);
7600 /*-----------------------------------------------------------------*/
7601 /* genPointerSet - stores the value into a pointer location */
7602 /*-----------------------------------------------------------------*/
7604 genPointerSet (iCode * ic, iCode *pi)
7606 operand *right, *result;
7607 sym_link *type, *etype;
7610 right = IC_RIGHT (ic);
7611 result = IC_RESULT (ic);
7613 /* depending on the type of pointer we need to
7614 move it to the correct pointer register */
7615 type = operandType (result);
7616 etype = getSpec (type);
7617 /* if left is of type of pointer then it is simple */
7618 if (IS_PTR (type) && !IS_FUNC (type->next))
7620 p_type = DCL_TYPE (type);
7624 /* we have to go by the storage class */
7625 p_type = PTR_TYPE (SPEC_OCLS (etype));
7628 /* now that we have the pointer type we assign
7629 the pointer values */
7635 genNearPointerSet (right, result, ic, pi);
7639 genPagedPointerSet (right, result, ic, pi);
7643 genFarPointerSet (right, result, ic, pi);
7647 genGenPointerSet (right, result, ic, pi);
7653 /*-----------------------------------------------------------------*/
7654 /* genIfx - generate code for Ifx statement */
7655 /*-----------------------------------------------------------------*/
7657 genIfx (iCode * ic, iCode * popIc)
7659 operand *cond = IC_COND (ic);
7662 aopOp (cond, ic, FALSE);
7664 /* get the value into acc */
7665 if (AOP_TYPE (cond) != AOP_CRY)
7669 /* the result is now in the accumulator */
7670 freeAsmop (cond, NULL, ic, TRUE);
7672 /* if there was something to be popped then do it */
7676 /* if the condition is a bit variable */
7677 if (isbit && IS_ITEMP (cond) &&
7679 genIfxJump (ic, SPIL_LOC (cond)->rname);
7680 else if (isbit && !IS_ITEMP (cond))
7681 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7683 genIfxJump (ic, "a");
7688 /*-----------------------------------------------------------------*/
7689 /* genAddrOf - generates code for address of */
7690 /*-----------------------------------------------------------------*/
7692 genAddrOf (iCode * ic)
7694 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7697 aopOp (IC_RESULT (ic), ic, FALSE);
7699 /* if the operand is on the stack then we
7700 need to get the stack offset of this
7704 /* if it has an offset then we need to compute
7708 emitcode ("mov", "a,_bp");
7709 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7710 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7714 /* we can just move _bp */
7715 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7717 /* fill the result with zero */
7718 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7723 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7729 /* object not on stack then we need the name */
7730 size = AOP_SIZE (IC_RESULT (ic));
7735 char s[SDCC_NAME_MAX];
7737 sprintf (s, "#(%s >> %d)",
7741 sprintf (s, "#%s", sym->rname);
7742 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7746 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7750 /*-----------------------------------------------------------------*/
7751 /* genFarFarAssign - assignment when both are in far space */
7752 /*-----------------------------------------------------------------*/
7754 genFarFarAssign (operand * result, operand * right, iCode * ic)
7756 int size = AOP_SIZE (right);
7759 /* first push the right side on to the stack */
7762 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7764 emitcode ("push", "acc");
7767 freeAsmop (right, NULL, ic, FALSE);
7768 /* now assign DPTR to result */
7769 aopOp (result, ic, FALSE);
7770 size = AOP_SIZE (result);
7773 emitcode ("pop", "acc");
7774 aopPut (AOP (result), "a", --offset);
7776 freeAsmop (result, NULL, ic, FALSE);
7780 /*-----------------------------------------------------------------*/
7781 /* genAssign - generate code for assignment */
7782 /*-----------------------------------------------------------------*/
7784 genAssign (iCode * ic)
7786 operand *result, *right;
7788 unsigned long lit = 0L;
7790 result = IC_RESULT (ic);
7791 right = IC_RIGHT (ic);
7793 /* if they are the same */
7794 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7797 aopOp (right, ic, FALSE);
7799 /* special case both in far space */
7800 if (AOP_TYPE (right) == AOP_DPTR &&
7801 IS_TRUE_SYMOP (result) &&
7802 isOperandInFarSpace (result))
7805 genFarFarAssign (result, right, ic);
7809 aopOp (result, ic, TRUE);
7811 /* if they are the same registers */
7812 if (sameRegs (AOP (right), AOP (result)))
7815 /* if the result is a bit */
7816 if (AOP_TYPE (result) == AOP_CRY)
7819 /* if the right size is a literal then
7820 we know what the value is */
7821 if (AOP_TYPE (right) == AOP_LIT)
7823 if (((int) operandLitValue (right)))
7824 aopPut (AOP (result), one, 0);
7826 aopPut (AOP (result), zero, 0);
7830 /* the right is also a bit variable */
7831 if (AOP_TYPE (right) == AOP_CRY)
7833 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7834 aopPut (AOP (result), "c", 0);
7840 aopPut (AOP (result), "a", 0);
7844 /* bit variables done */
7846 size = AOP_SIZE (result);
7848 if (AOP_TYPE (right) == AOP_LIT)
7849 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7851 (AOP_TYPE (result) != AOP_REG) &&
7852 (AOP_TYPE (right) == AOP_LIT) &&
7853 !IS_FLOAT (operandType (right)) &&
7856 emitcode ("clr", "a");
7859 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7860 aopPut (AOP (result), "a", size);
7862 aopPut (AOP (result),
7863 aopGet (AOP (right), size, FALSE, FALSE),
7871 aopPut (AOP (result),
7872 aopGet (AOP (right), offset, FALSE, FALSE),
7879 freeAsmop (right, NULL, ic, TRUE);
7880 freeAsmop (result, NULL, ic, TRUE);
7883 /*-----------------------------------------------------------------*/
7884 /* genJumpTab - genrates code for jump table */
7885 /*-----------------------------------------------------------------*/
7887 genJumpTab (iCode * ic)
7892 aopOp (IC_JTCOND (ic), ic, FALSE);
7893 /* get the condition into accumulator */
7894 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7896 /* multiply by three */
7897 emitcode ("add", "a,acc");
7898 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7899 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7901 jtab = newiTempLabel (NULL);
7902 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7903 emitcode ("jmp", "@a+dptr");
7904 emitcode ("", "%05d$:", jtab->key + 100);
7905 /* now generate the jump labels */
7906 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7907 jtab = setNextItem (IC_JTLABELS (ic)))
7908 emitcode ("ljmp", "%05d$", jtab->key + 100);
7912 /*-----------------------------------------------------------------*/
7913 /* genCast - gen code for casting */
7914 /*-----------------------------------------------------------------*/
7916 genCast (iCode * ic)
7918 operand *result = IC_RESULT (ic);
7919 sym_link *ctype = operandType (IC_LEFT (ic));
7920 sym_link *rtype = operandType (IC_RIGHT (ic));
7921 operand *right = IC_RIGHT (ic);
7924 /* if they are equivalent then do nothing */
7925 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7928 aopOp (right, ic, FALSE);
7929 aopOp (result, ic, FALSE);
7931 /* if the result is a bit */
7932 if (AOP_TYPE (result) == AOP_CRY)
7934 /* if the right size is a literal then
7935 we know what the value is */
7936 if (AOP_TYPE (right) == AOP_LIT)
7938 if (((int) operandLitValue (right)))
7939 aopPut (AOP (result), one, 0);
7941 aopPut (AOP (result), zero, 0);
7946 /* the right is also a bit variable */
7947 if (AOP_TYPE (right) == AOP_CRY)
7949 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7950 aopPut (AOP (result), "c", 0);
7956 aopPut (AOP (result), "a", 0);
7960 /* if they are the same size : or less */
7961 if (AOP_SIZE (result) <= AOP_SIZE (right))
7964 /* if they are in the same place */
7965 if (sameRegs (AOP (right), AOP (result)))
7968 /* if they in different places then copy */
7969 size = AOP_SIZE (result);
7973 aopPut (AOP (result),
7974 aopGet (AOP (right), offset, FALSE, FALSE),
7982 /* if the result is of type pointer */
7987 sym_link *type = operandType (right);
7988 sym_link *etype = getSpec (type);
7990 /* pointer to generic pointer */
7991 if (IS_GENPTR (ctype))
7996 p_type = DCL_TYPE (type);
7999 /* we have to go by the storage class */
8000 p_type = PTR_TYPE (SPEC_OCLS (etype));
8003 /* the first two bytes are known */
8004 size = GPTRSIZE - 1;
8008 aopPut (AOP (result),
8009 aopGet (AOP (right), offset, FALSE, FALSE),
8013 /* the last byte depending on type */
8031 /* this should never happen */
8032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8033 "got unknown pointer type");
8036 aopPut (AOP (result), l, GPTRSIZE - 1);
8040 /* just copy the pointers */
8041 size = AOP_SIZE (result);
8045 aopPut (AOP (result),
8046 aopGet (AOP (right), offset, FALSE, FALSE),
8053 /* so we now know that the size of destination is greater
8054 than the size of the source */
8055 /* we move to result for the size of source */
8056 size = AOP_SIZE (right);
8060 aopPut (AOP (result),
8061 aopGet (AOP (right), offset, FALSE, FALSE),
8066 /* now depending on the sign of the source && destination */
8067 size = AOP_SIZE (result) - AOP_SIZE (right);
8068 /* if unsigned or not an integral type */
8069 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8072 aopPut (AOP (result), zero, offset++);
8076 /* we need to extend the sign :{ */
8077 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8080 emitcode ("rlc", "a");
8081 emitcode ("subb", "a,acc");
8083 aopPut (AOP (result), "a", offset++);
8086 /* we are done hurray !!!! */
8089 freeAsmop (right, NULL, ic, TRUE);
8090 freeAsmop (result, NULL, ic, TRUE);
8094 /*-----------------------------------------------------------------*/
8095 /* genDjnz - generate decrement & jump if not zero instrucion */
8096 /*-----------------------------------------------------------------*/
8098 genDjnz (iCode * ic, iCode * ifx)
8104 /* if the if condition has a false label
8105 then we cannot save */
8109 /* if the minus is not of the form
8111 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8112 !IS_OP_LITERAL (IC_RIGHT (ic)))
8115 if (operandLitValue (IC_RIGHT (ic)) != 1)
8118 /* if the size of this greater than one then no
8120 if (getSize (operandType (IC_RESULT (ic))) > 1)
8123 /* otherwise we can save BIG */
8124 lbl = newiTempLabel (NULL);
8125 lbl1 = newiTempLabel (NULL);
8127 aopOp (IC_RESULT (ic), ic, FALSE);
8129 if (AOP_NEEDSACC(IC_RESULT(ic)))
8131 /* If the result is accessed indirectly via
8132 * the accumulator, we must explicitly write
8133 * it back after the decrement.
8135 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8137 if (strcmp(rByte, "a"))
8139 /* Something is hopelessly wrong */
8140 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8141 __FILE__, __LINE__);
8142 /* We can just give up; the generated code will be inefficient,
8145 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8148 emitcode ("dec", "%s", rByte);
8149 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8150 emitcode ("jnz", "%05d$", lbl->key + 100);
8152 else if (IS_AOP_PREG (IC_RESULT (ic)))
8154 emitcode ("dec", "%s",
8155 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8156 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8157 emitcode ("jnz", "%05d$", lbl->key + 100);
8161 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8164 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8165 emitcode ("", "%05d$:", lbl->key + 100);
8166 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8167 emitcode ("", "%05d$:", lbl1->key + 100);
8169 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8174 /*-----------------------------------------------------------------*/
8175 /* genReceive - generate code for a receive iCode */
8176 /*-----------------------------------------------------------------*/
8178 genReceive (iCode * ic)
8180 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8181 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8182 IS_TRUE_SYMOP (IC_RESULT (ic))))
8185 int size = getSize (operandType (IC_RESULT (ic)));
8186 int offset = fReturnSizeMCS51 - size;
8189 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8190 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8193 aopOp (IC_RESULT (ic), ic, FALSE);
8194 size = AOP_SIZE (IC_RESULT (ic));
8198 emitcode ("pop", "acc");
8199 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8206 aopOp (IC_RESULT (ic), ic, FALSE);
8208 assignResultValue (IC_RESULT (ic));
8211 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8214 /*-----------------------------------------------------------------*/
8215 /* gen51Code - generate code for 8051 based controllers */
8216 /*-----------------------------------------------------------------*/
8218 gen51Code (iCode * lic)
8223 lineHead = lineCurr = NULL;
8225 /* print the allocation information */
8227 printAllocInfo (currFunc, codeOutFile);
8228 /* if debug information required */
8229 /* if (options.debug && currFunc) { */
8232 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8234 if (IS_STATIC (currFunc->etype))
8235 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8237 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8240 /* stack pointer name */
8241 if (options.useXstack)
8247 for (ic = lic; ic; ic = ic->next)
8250 if (cln != ic->lineno)
8255 emitcode ("", "C$%s$%d$%d$%d ==.",
8256 FileBaseName (ic->filename), ic->lineno,
8257 ic->level, ic->block);
8260 emitcode (";", "%s %d", ic->filename, ic->lineno);
8263 /* if the result is marked as
8264 spilt and rematerializable or code for
8265 this has already been generated then
8267 if (resultRemat (ic) || ic->generated)
8270 /* depending on the operation */
8290 /* IPOP happens only when trying to restore a
8291 spilt live range, if there is an ifx statement
8292 following this pop then the if statement might
8293 be using some of the registers being popped which
8294 would destory the contents of the register so
8295 we need to check for this condition and handle it */
8297 ic->next->op == IFX &&
8298 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8299 genIfx (ic->next, ic);
8317 genEndFunction (ic);
8337 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8354 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8358 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8365 /* note these two are xlated by algebraic equivalence
8366 during parsing SDCC.y */
8367 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8368 "got '>=' or '<=' shouldn't have come here");
8372 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8384 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8388 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8392 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8419 case GET_VALUE_AT_ADDRESS:
8420 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8424 if (POINTER_SET (ic))
8425 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8451 addSet (&_G.sendSet, ic);
8460 /* now we are ready to call the
8461 peep hole optimizer */
8462 if (!options.nopeep)
8463 peepHole (&lineHead);
8465 /* now do the actual printing */
8466 printLine (lineHead, codeOutFile);