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[INITIAL_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;
1621 /* if this is not a parm push : ie. it is spill push
1622 and spill push is always done on the local stack */
1626 /* and the item is spilt then do nothing */
1627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1630 aopOp (IC_LEFT (ic), ic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (ic));
1632 /* push it on the stack */
1635 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1641 emitcode ("push", "%s", l);
1646 /* this is a paramter push: in this case we call
1647 the routine to find the call and save those
1648 registers that need to be saved */
1651 /* if use external stack then call the external
1652 stack pushing routine */
1653 if (options.useXstack)
1659 /* then do the push */
1660 aopOp (IC_LEFT (ic), ic, FALSE);
1663 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1664 size = AOP_SIZE (IC_LEFT (ic));
1668 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1669 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1670 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1673 emitcode ("mov", "a,%s", l);
1674 emitcode ("push", "acc");
1677 emitcode ("push", "%s", l);
1680 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1683 /*-----------------------------------------------------------------*/
1684 /* genIpop - recover the registers: can happen only for spilling */
1685 /*-----------------------------------------------------------------*/
1687 genIpop (iCode * ic)
1692 /* if the temp was not pushed then */
1693 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1696 aopOp (IC_LEFT (ic), ic, FALSE);
1697 size = AOP_SIZE (IC_LEFT (ic));
1698 offset = (size - 1);
1700 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1703 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* unsaveRBank - restores the resgister bank from stack */
1708 /*-----------------------------------------------------------------*/
1710 unsaveRBank (int bank, iCode * ic, bool popPsw)
1718 if (options.useXstack)
1721 r = getFreePtr (ic, &aop, FALSE);
1724 emitcode ("mov", "%s,_spx", r->name);
1725 emitcode ("movx", "a,@%s", r->name);
1726 emitcode ("mov", "psw,a");
1727 emitcode ("dec", "%s", r->name);
1731 emitcode ("pop", "psw");
1734 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1736 if (options.useXstack)
1738 emitcode ("movx", "a,@%s", r->name);
1739 emitcode ("mov", "(%s+%d),a",
1740 regs8051[i].base, 8 * bank + regs8051[i].offset);
1741 emitcode ("dec", "%s", r->name);
1745 emitcode ("pop", "(%s+%d)",
1746 regs8051[i].base, 8 * bank + regs8051[i].offset);
1749 if (options.useXstack)
1752 emitcode ("mov", "_spx,%s", r->name);
1753 freeAsmop (NULL, aop, ic, TRUE);
1758 /*-----------------------------------------------------------------*/
1759 /* saveRBank - saves an entire register bank on the stack */
1760 /*-----------------------------------------------------------------*/
1762 saveRBank (int bank, iCode * ic, bool pushPsw)
1768 if (options.useXstack)
1772 r = getFreePtr (ic, &aop, FALSE);
1773 emitcode ("mov", "%s,_spx", r->name);
1777 for (i = 0; i < mcs51_nRegs; i++)
1779 if (options.useXstack)
1781 emitcode ("inc", "%s", r->name);
1782 emitcode ("mov", "a,(%s+%d)",
1783 regs8051[i].base, 8 * bank + regs8051[i].offset);
1784 emitcode ("movx", "@%s,a", r->name);
1787 emitcode ("push", "(%s+%d)",
1788 regs8051[i].base, 8 * bank + regs8051[i].offset);
1793 if (options.useXstack)
1795 emitcode ("mov", "a,psw");
1796 emitcode ("movx", "@%s,a", r->name);
1797 emitcode ("inc", "%s", r->name);
1798 emitcode ("mov", "_spx,%s", r->name);
1799 freeAsmop (NULL, aop, ic, TRUE);
1803 emitcode ("push", "psw");
1805 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1811 /*-----------------------------------------------------------------*/
1812 /* genCall - generates a call statement */
1813 /*-----------------------------------------------------------------*/
1815 genCall (iCode * ic)
1819 /* if send set is not empty the assign */
1824 for (sic = setFirstItem (_G.sendSet); sic;
1825 sic = setNextItem (_G.sendSet))
1827 int size, offset = 0;
1828 aopOp (IC_LEFT (sic), sic, FALSE);
1829 size = AOP_SIZE (IC_LEFT (sic));
1832 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1834 if (strcmp (l, fReturn[offset]))
1835 emitcode ("mov", "%s,%s",
1840 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1845 /* if we are calling a function that is not using
1846 the same register bank then we need to save the
1847 destination registers on the stack */
1848 detype = getSpec (operandType (IC_LEFT (ic)));
1850 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1851 IS_ISR (currFunc->etype) &&
1853 saveRBank (SPEC_BANK (detype), ic, TRUE);
1854 } else /* no need to save if we just saved the whole bank */ {
1855 /* if caller saves & we have not saved then */
1861 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1862 OP_SYMBOL (IC_LEFT (ic))->rname :
1863 OP_SYMBOL (IC_LEFT (ic))->name));
1865 /* if we need assign a result value */
1866 if ((IS_ITEMP (IC_RESULT (ic)) &&
1867 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1868 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1869 IS_TRUE_SYMOP (IC_RESULT (ic)))
1873 aopOp (IC_RESULT (ic), ic, FALSE);
1876 assignResultValue (IC_RESULT (ic));
1878 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1881 /* adjust the stack for parameters if
1886 if (ic->parmBytes > 3)
1888 emitcode ("mov", "a,%s", spname);
1889 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1890 emitcode ("mov", "%s,a", spname);
1893 for (i = 0; i < ic->parmBytes; i++)
1894 emitcode ("dec", "%s", spname);
1898 /* if register bank was saved then pop them */
1900 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
1902 /* if we hade saved some registers then unsave them */
1903 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1904 unsaveRegisters (ic);
1909 /*-----------------------------------------------------------------*/
1910 /* genPcall - generates a call by pointer statement */
1911 /*-----------------------------------------------------------------*/
1913 genPcall (iCode * ic)
1916 symbol *rlbl = newiTempLabel (NULL);
1919 /* if caller saves & we have not saved then */
1923 /* if we are calling a function that is not using
1924 the same register bank then we need to save the
1925 destination registers on the stack */
1926 detype = getSpec (operandType (IC_LEFT (ic)));
1928 IS_ISR (currFunc->etype) &&
1929 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1930 saveRBank (SPEC_BANK (detype), ic, TRUE);
1933 /* push the return address on to the stack */
1934 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1935 emitcode ("push", "acc");
1936 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1937 emitcode ("push", "acc");
1939 /* now push the calling address */
1940 aopOp (IC_LEFT (ic), ic, FALSE);
1942 pushSide (IC_LEFT (ic), FPTRSIZE);
1944 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1946 /* if send set is not empty the assign */
1951 for (sic = setFirstItem (_G.sendSet); sic;
1952 sic = setNextItem (_G.sendSet))
1954 int size, offset = 0;
1955 aopOp (IC_LEFT (sic), sic, FALSE);
1956 size = AOP_SIZE (IC_LEFT (sic));
1959 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1961 if (strcmp (l, fReturn[offset]))
1962 emitcode ("mov", "%s,%s",
1967 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1972 emitcode ("ret", "");
1973 emitcode ("", "%05d$:", (rlbl->key + 100));
1976 /* if we need assign a result value */
1977 if ((IS_ITEMP (IC_RESULT (ic)) &&
1978 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1979 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1980 IS_TRUE_SYMOP (IC_RESULT (ic)))
1984 aopOp (IC_RESULT (ic), ic, FALSE);
1987 assignResultValue (IC_RESULT (ic));
1989 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1992 /* adjust the stack for parameters if
1997 if (ic->parmBytes > 3)
1999 emitcode ("mov", "a,%s", spname);
2000 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2001 emitcode ("mov", "%s,a", spname);
2004 for (i = 0; i < ic->parmBytes; i++)
2005 emitcode ("dec", "%s", spname);
2009 /* if register bank was saved then unsave them */
2011 (SPEC_BANK (currFunc->etype) !=
2012 SPEC_BANK (detype)))
2013 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2015 /* if we hade saved some registers then
2018 unsaveRegisters (ic);
2022 /*-----------------------------------------------------------------*/
2023 /* resultRemat - result is rematerializable */
2024 /*-----------------------------------------------------------------*/
2026 resultRemat (iCode * ic)
2028 if (SKIP_IC (ic) || ic->op == IFX)
2031 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2033 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2034 if (sym->remat && !POINTER_SET (ic))
2041 #if defined(__BORLANDC__) || defined(_MSC_VER)
2042 #define STRCASECMP stricmp
2044 #define STRCASECMP strcasecmp
2047 /*-----------------------------------------------------------------*/
2048 /* inExcludeList - return 1 if the string is in exclude Reg list */
2049 /*-----------------------------------------------------------------*/
2051 inExcludeList (char *s)
2055 if (options.excludeRegs[i] &&
2056 STRCASECMP (options.excludeRegs[i], "none") == 0)
2059 for (i = 0; options.excludeRegs[i]; i++)
2061 if (options.excludeRegs[i] &&
2062 STRCASECMP (s, options.excludeRegs[i]) == 0)
2068 /*-----------------------------------------------------------------*/
2069 /* genFunction - generated code for function entry */
2070 /*-----------------------------------------------------------------*/
2072 genFunction (iCode * ic)
2078 /* create the function header */
2079 emitcode (";", "-----------------------------------------");
2080 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2081 emitcode (";", "-----------------------------------------");
2083 emitcode ("", "%s:", sym->rname);
2084 fetype = getSpec (operandType (IC_LEFT (ic)));
2086 /* if critical function then turn interrupts off */
2087 if (SPEC_CRTCL (fetype))
2088 emitcode ("clr", "ea");
2090 /* here we need to generate the equates for the
2091 register bank if required */
2092 if (SPEC_BANK (fetype) != rbank)
2096 rbank = SPEC_BANK (fetype);
2097 for (i = 0; i < mcs51_nRegs; i++)
2099 if (strcmp (regs8051[i].base, "0") == 0)
2100 emitcode ("", "%s = 0x%02x",
2102 8 * rbank + regs8051[i].offset);
2104 emitcode ("", "%s = %s + 0x%02x",
2107 8 * rbank + regs8051[i].offset);
2111 /* if this is an interrupt service routine then
2112 save acc, b, dpl, dph */
2113 if (IS_ISR (sym->etype))
2116 if (!inExcludeList ("acc"))
2117 emitcode ("push", "acc");
2118 if (!inExcludeList ("b"))
2119 emitcode ("push", "b");
2120 if (!inExcludeList ("dpl"))
2121 emitcode ("push", "dpl");
2122 if (!inExcludeList ("dph"))
2123 emitcode ("push", "dph");
2124 /* if this isr has no bank i.e. is going to
2125 run with bank 0 , then we need to save more
2127 if (!SPEC_BANK (sym->etype))
2130 /* if this function does not call any other
2131 function then we can be economical and
2132 save only those registers that are used */
2137 /* if any registers used */
2140 /* save the registers used */
2141 for (i = 0; i < sym->regsUsed->size; i++)
2143 if (bitVectBitValue (sym->regsUsed, i) ||
2144 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2145 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2152 /* this function has a function call cannot
2153 determines register usage so we will have to push the
2155 saveRBank (0, ic, FALSE);
2161 /* if callee-save to be used for this function
2162 then save the registers being used in this function */
2163 if (sym->calleeSave)
2167 /* if any registers used */
2170 /* save the registers used */
2171 for (i = 0; i < sym->regsUsed->size; i++)
2173 if (bitVectBitValue (sym->regsUsed, i) ||
2174 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2176 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2184 /* set the register bank to the desired value */
2185 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2187 emitcode ("push", "psw");
2188 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2191 if (IS_RENT (sym->etype) || options.stackAuto)
2194 if (options.useXstack)
2196 emitcode ("mov", "r0,%s", spname);
2197 emitcode ("mov", "a,_bp");
2198 emitcode ("movx", "@r0,a");
2199 emitcode ("inc", "%s", spname);
2203 /* set up the stack */
2204 emitcode ("push", "_bp"); /* save the callers stack */
2206 emitcode ("mov", "_bp,%s", spname);
2209 /* adjust the stack for the function */
2215 werror (W_STACK_OVERFLOW, sym->name);
2217 if (i > 3 && sym->recvSize < 4)
2220 emitcode ("mov", "a,sp");
2221 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2222 emitcode ("mov", "sp,a");
2227 emitcode ("inc", "sp");
2233 emitcode ("mov", "a,_spx");
2234 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2235 emitcode ("mov", "_spx,a");
2240 /*-----------------------------------------------------------------*/
2241 /* genEndFunction - generates epilogue for functions */
2242 /*-----------------------------------------------------------------*/
2244 genEndFunction (iCode * ic)
2246 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2248 if (IS_RENT (sym->etype) || options.stackAuto)
2250 emitcode ("mov", "%s,_bp", spname);
2253 /* if use external stack but some variables were
2254 added to the local stack then decrement the
2256 if (options.useXstack && sym->stack)
2258 emitcode ("mov", "a,sp");
2259 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2260 emitcode ("mov", "sp,a");
2264 if ((IS_RENT (sym->etype) || options.stackAuto))
2266 if (options.useXstack)
2268 emitcode ("mov", "r0,%s", spname);
2269 emitcode ("movx", "a,@r0");
2270 emitcode ("mov", "_bp,a");
2271 emitcode ("dec", "%s", spname);
2275 emitcode ("pop", "_bp");
2279 /* restore the register bank */
2280 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2281 emitcode ("pop", "psw");
2283 if (IS_ISR (sym->etype))
2286 /* now we need to restore the registers */
2287 /* if this isr has no bank i.e. is going to
2288 run with bank 0 , then we need to save more
2290 if (!SPEC_BANK (sym->etype))
2293 /* if this function does not call any other
2294 function then we can be economical and
2295 save only those registers that are used */
2300 /* if any registers used */
2303 /* save the registers used */
2304 for (i = sym->regsUsed->size; i >= 0; i--)
2306 if (bitVectBitValue (sym->regsUsed, i) ||
2307 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2308 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2315 /* this function has a function call cannot
2316 determines register usage so we will have to pop the
2318 unsaveRBank (0, ic, FALSE);
2322 if (!inExcludeList ("dph"))
2323 emitcode ("pop", "dph");
2324 if (!inExcludeList ("dpl"))
2325 emitcode ("pop", "dpl");
2326 if (!inExcludeList ("b"))
2327 emitcode ("pop", "b");
2328 if (!inExcludeList ("acc"))
2329 emitcode ("pop", "acc");
2331 if (SPEC_CRTCL (sym->etype))
2332 emitcode ("setb", "ea");
2334 /* if debug then send end of function */
2335 /* if (options.debug && currFunc) { */
2339 emitcode ("", "C$%s$%d$%d$%d ==.",
2340 FileBaseName (ic->filename), currFunc->lastLine,
2341 ic->level, ic->block);
2342 if (IS_STATIC (currFunc->etype))
2343 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2345 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2349 emitcode ("reti", "");
2353 if (SPEC_CRTCL (sym->etype))
2354 emitcode ("setb", "ea");
2356 if (sym->calleeSave)
2360 /* if any registers used */
2363 /* save the registers used */
2364 for (i = sym->regsUsed->size; i >= 0; i--)
2366 if (bitVectBitValue (sym->regsUsed, i) ||
2367 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2368 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2374 /* if debug then send end of function */
2378 emitcode ("", "C$%s$%d$%d$%d ==.",
2379 FileBaseName (ic->filename), currFunc->lastLine,
2380 ic->level, ic->block);
2381 if (IS_STATIC (currFunc->etype))
2382 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2384 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2388 emitcode ("ret", "");
2393 /*-----------------------------------------------------------------*/
2394 /* genRet - generate code for return statement */
2395 /*-----------------------------------------------------------------*/
2399 int size, offset = 0, pushed = 0;
2401 /* if we have no return value then
2402 just generate the "ret" */
2406 /* we have something to return then
2407 move the return value into place */
2408 aopOp (IC_LEFT (ic), ic, FALSE);
2409 size = AOP_SIZE (IC_LEFT (ic));
2414 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2417 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2419 emitcode ("push", "%s", l);
2424 l = aopGet (AOP (IC_LEFT (ic)), offset,
2426 if (strcmp (fReturn[offset], l))
2427 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2436 if (strcmp (fReturn[pushed], "a"))
2437 emitcode ("pop", fReturn[pushed]);
2439 emitcode ("pop", "acc");
2442 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2445 /* generate a jump to the return label
2446 if the next is not the return statement */
2447 if (!(ic->next && ic->next->op == LABEL &&
2448 IC_LABEL (ic->next) == returnLabel))
2450 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2454 /*-----------------------------------------------------------------*/
2455 /* genLabel - generates a label */
2456 /*-----------------------------------------------------------------*/
2458 genLabel (iCode * ic)
2460 /* special case never generate */
2461 if (IC_LABEL (ic) == entryLabel)
2464 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2467 /*-----------------------------------------------------------------*/
2468 /* genGoto - generates a ljmp */
2469 /*-----------------------------------------------------------------*/
2471 genGoto (iCode * ic)
2473 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2476 /*-----------------------------------------------------------------*/
2477 /* findLabelBackwards: walks back through the iCode chain looking */
2478 /* for the given label. Returns number of iCode instructions */
2479 /* between that label and given ic. */
2480 /* Returns zero if label not found. */
2481 /*-----------------------------------------------------------------*/
2483 findLabelBackwards (iCode * ic, int key)
2492 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2494 /* printf("findLabelBackwards = %d\n", count); */
2502 /*-----------------------------------------------------------------*/
2503 /* genPlusIncr :- does addition with increment if possible */
2504 /*-----------------------------------------------------------------*/
2506 genPlusIncr (iCode * ic)
2508 unsigned int icount;
2509 unsigned int size = getDataSize (IC_RESULT (ic));
2511 /* will try to generate an increment */
2512 /* if the right side is not a literal
2514 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2517 /* if the literal value of the right hand side
2518 is greater than 4 then it is not worth it */
2519 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2522 /* if increment 16 bits in register */
2523 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2531 /* If the next instruction is a goto and the goto target
2532 * is < 10 instructions previous to this, we can generate
2533 * jumps straight to that target.
2535 if (ic->next && ic->next->op == GOTO
2536 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2537 && labelRange <= 10)
2539 emitcode (";", "tail increment optimized");
2540 tlbl = IC_LABEL (ic->next);
2545 tlbl = newiTempLabel (NULL);
2548 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2549 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2550 IS_AOP_PREG (IC_RESULT (ic)))
2551 emitcode ("cjne", "%s,#0x00,%05d$"
2552 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2556 emitcode ("clr", "a");
2557 emitcode ("cjne", "a,%s,%05d$"
2558 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2562 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2565 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2566 IS_AOP_PREG (IC_RESULT (ic)))
2567 emitcode ("cjne", "%s,#0x00,%05d$"
2568 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2571 emitcode ("cjne", "a,%s,%05d$"
2572 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2575 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2579 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2580 IS_AOP_PREG (IC_RESULT (ic)))
2581 emitcode ("cjne", "%s,#0x00,%05d$"
2582 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2586 emitcode ("cjne", "a,%s,%05d$"
2587 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2590 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2595 emitcode ("", "%05d$:", tlbl->key + 100);
2600 /* if the sizes are greater than 1 then we cannot */
2601 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2602 AOP_SIZE (IC_LEFT (ic)) > 1)
2605 /* we can if the aops of the left & result match or
2606 if they are in registers and the registers are the
2608 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2613 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2614 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2615 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2621 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2630 /*-----------------------------------------------------------------*/
2631 /* outBitAcc - output a bit in acc */
2632 /*-----------------------------------------------------------------*/
2634 outBitAcc (operand * result)
2636 symbol *tlbl = newiTempLabel (NULL);
2637 /* if the result is a bit */
2638 if (AOP_TYPE (result) == AOP_CRY)
2640 aopPut (AOP (result), "a", 0);
2644 emitcode ("jz", "%05d$", tlbl->key + 100);
2645 emitcode ("mov", "a,%s", one);
2646 emitcode ("", "%05d$:", tlbl->key + 100);
2651 /*-----------------------------------------------------------------*/
2652 /* genPlusBits - generates code for addition of two bits */
2653 /*-----------------------------------------------------------------*/
2655 genPlusBits (iCode * ic)
2657 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2659 symbol *lbl = newiTempLabel (NULL);
2660 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2661 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2662 emitcode ("cpl", "c");
2663 emitcode ("", "%05d$:", (lbl->key + 100));
2664 outBitC (IC_RESULT (ic));
2668 emitcode ("clr", "a");
2669 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2670 emitcode ("rlc", "a");
2671 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2672 emitcode ("addc", "a,#0x00");
2673 outAcc (IC_RESULT (ic));
2678 /* This is the original version of this code.
2680 * This is being kept around for reference,
2681 * because I am not entirely sure I got it right...
2684 adjustArithmeticResult (iCode * ic)
2686 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2687 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2688 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2689 aopPut (AOP (IC_RESULT (ic)),
2690 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2693 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2694 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2695 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2696 aopPut (AOP (IC_RESULT (ic)),
2697 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2700 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2701 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2702 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2703 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2704 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2707 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2708 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2712 /* This is the pure and virtuous version of this code.
2713 * I'm pretty certain it's right, but not enough to toss the old
2717 adjustArithmeticResult (iCode * ic)
2719 if (opIsGptr (IC_RESULT (ic)) &&
2720 opIsGptr (IC_LEFT (ic)) &&
2721 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2723 aopPut (AOP (IC_RESULT (ic)),
2724 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2728 if (opIsGptr (IC_RESULT (ic)) &&
2729 opIsGptr (IC_RIGHT (ic)) &&
2730 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2732 aopPut (AOP (IC_RESULT (ic)),
2733 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2737 if (opIsGptr (IC_RESULT (ic)) &&
2738 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2739 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2740 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2741 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2744 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2745 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2750 /*-----------------------------------------------------------------*/
2751 /* genPlus - generates code for addition */
2752 /*-----------------------------------------------------------------*/
2754 genPlus (iCode * ic)
2756 int size, offset = 0;
2758 /* special cases :- */
2760 aopOp (IC_LEFT (ic), ic, FALSE);
2761 aopOp (IC_RIGHT (ic), ic, FALSE);
2762 aopOp (IC_RESULT (ic), ic, TRUE);
2764 /* if literal, literal on the right or
2765 if left requires ACC or right is already
2767 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2768 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2769 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2771 operand *t = IC_RIGHT (ic);
2772 IC_RIGHT (ic) = IC_LEFT (ic);
2776 /* if both left & right are in bit
2778 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2779 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2785 /* if left in bit space & right literal */
2786 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2787 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2789 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2790 /* if result in bit space */
2791 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2793 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2794 emitcode ("cpl", "c");
2795 outBitC (IC_RESULT (ic));
2799 size = getDataSize (IC_RESULT (ic));
2802 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2803 emitcode ("addc", "a,#00");
2804 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2810 /* if I can do an increment instead
2811 of add then GOOD for ME */
2812 if (genPlusIncr (ic) == TRUE)
2815 size = getDataSize (IC_RESULT (ic));
2819 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2821 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2823 emitcode ("add", "a,%s",
2824 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2826 emitcode ("addc", "a,%s",
2827 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2831 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2833 emitcode ("add", "a,%s",
2834 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2836 emitcode ("addc", "a,%s",
2837 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2839 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2842 adjustArithmeticResult (ic);
2845 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2846 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2847 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2850 /*-----------------------------------------------------------------*/
2851 /* genMinusDec :- does subtraction with deccrement if possible */
2852 /*-----------------------------------------------------------------*/
2854 genMinusDec (iCode * ic)
2856 unsigned int icount;
2857 unsigned int size = getDataSize (IC_RESULT (ic));
2859 /* will try to generate an increment */
2860 /* if the right side is not a literal
2862 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2865 /* if the literal value of the right hand side
2866 is greater than 4 then it is not worth it */
2867 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2870 /* if decrement 16 bits in register */
2871 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2879 /* If the next instruction is a goto and the goto target
2880 * is <= 10 instructions previous to this, we can generate
2881 * jumps straight to that target.
2883 if (ic->next && ic->next->op == GOTO
2884 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2885 && labelRange <= 10)
2887 emitcode (";", "tail decrement optimized");
2888 tlbl = IC_LABEL (ic->next);
2893 tlbl = newiTempLabel (NULL);
2897 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2898 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2899 IS_AOP_PREG (IC_RESULT (ic)))
2900 emitcode ("cjne", "%s,#0xff,%05d$"
2901 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2905 emitcode ("mov", "a,#0xff");
2906 emitcode ("cjne", "a,%s,%05d$"
2907 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2910 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2914 IS_AOP_PREG (IC_RESULT (ic)))
2915 emitcode ("cjne", "%s,#0xff,%05d$"
2916 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2920 emitcode ("cjne", "a,%s,%05d$"
2921 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2924 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2928 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2929 IS_AOP_PREG (IC_RESULT (ic)))
2930 emitcode ("cjne", "%s,#0xff,%05d$"
2931 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2935 emitcode ("cjne", "a,%s,%05d$"
2936 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2939 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2943 emitcode ("", "%05d$:", tlbl->key + 100);
2948 /* if the sizes are greater than 1 then we cannot */
2949 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2950 AOP_SIZE (IC_LEFT (ic)) > 1)
2953 /* we can if the aops of the left & result match or
2954 if they are in registers and the registers are the
2956 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2960 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
2968 /*-----------------------------------------------------------------*/
2969 /* addSign - complete with sign */
2970 /*-----------------------------------------------------------------*/
2972 addSign (operand * result, int offset, int sign)
2974 int size = (getDataSize (result) - offset);
2979 emitcode ("rlc", "a");
2980 emitcode ("subb", "a,acc");
2982 aopPut (AOP (result), "a", offset++);
2986 aopPut (AOP (result), zero, offset++);
2990 /*-----------------------------------------------------------------*/
2991 /* genMinusBits - generates code for subtraction of two bits */
2992 /*-----------------------------------------------------------------*/
2994 genMinusBits (iCode * ic)
2996 symbol *lbl = newiTempLabel (NULL);
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2999 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3000 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3001 emitcode ("cpl", "c");
3002 emitcode ("", "%05d$:", (lbl->key + 100));
3003 outBitC (IC_RESULT (ic));
3007 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3008 emitcode ("subb", "a,acc");
3009 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3010 emitcode ("inc", "a");
3011 emitcode ("", "%05d$:", (lbl->key + 100));
3012 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3013 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3017 /*-----------------------------------------------------------------*/
3018 /* genMinus - generates code for subtraction */
3019 /*-----------------------------------------------------------------*/
3021 genMinus (iCode * ic)
3023 int size, offset = 0;
3024 unsigned long lit = 0L;
3026 aopOp (IC_LEFT (ic), ic, FALSE);
3027 aopOp (IC_RIGHT (ic), ic, FALSE);
3028 aopOp (IC_RESULT (ic), ic, TRUE);
3030 /* special cases :- */
3031 /* if both left & right are in bit space */
3032 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3033 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3039 /* if I can do an decrement instead
3040 of subtract then GOOD for ME */
3041 if (genMinusDec (ic) == TRUE)
3044 size = getDataSize (IC_RESULT (ic));
3046 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3052 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3056 /* if literal, add a,#-lit, else normal subb */
3059 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3060 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3061 emitcode ("subb", "a,%s",
3062 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3065 /* first add without previous c */
3067 emitcode ("add", "a,#0x%02x",
3068 (unsigned int) (lit & 0x0FFL));
3070 emitcode ("addc", "a,#0x%02x",
3071 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3073 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3076 adjustArithmeticResult (ic);
3079 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3080 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* genMultbits :- multiplication of bits */
3087 /*-----------------------------------------------------------------*/
3089 genMultbits (operand * left,
3093 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3094 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3099 /*-----------------------------------------------------------------*/
3100 /* genMultOneByte : 8*8=8/16 bit multiplication */
3101 /*-----------------------------------------------------------------*/
3103 genMultOneByte (operand * left,
3107 sym_link *opetype = operandType (result);
3109 int size=AOP_SIZE(result);
3111 //emitcode (";",__FUNCTION__);
3112 if (size<1 || size>2) {
3113 // this should never happen
3114 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3115 AOP_SIZE(result), __FILE__, lineno);
3119 /* (if two literals: the value is computed before) */
3120 /* if one literal, literal on the right */
3121 if (AOP_TYPE (left) == AOP_LIT)
3126 //emitcode (";", "swapped left and right");
3129 if (SPEC_USIGN(opetype)
3130 // ignore the sign of left and right, what else can we do?
3131 || (SPEC_USIGN(operandType(left)) &&
3132 SPEC_USIGN(operandType(right)))) {
3133 // just an unsigned 8*8=8/16 multiply
3134 //emitcode (";","unsigned");
3135 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3136 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3137 emitcode ("mul", "ab");
3138 aopPut (AOP (result), "a", 0);
3140 aopPut (AOP (result), "b", 1);
3145 // we have to do a signed multiply
3147 //emitcode (";", "signed");
3148 emitcode ("clr", "F0"); // reset sign flag
3149 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3150 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3152 lbl=newiTempLabel(NULL);
3153 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3154 // left side is negative, 8-bit two's complement, this fails for -128
3155 emitcode ("setb", "F0"); // set sign flag
3156 emitcode ("cpl", "a");
3157 emitcode ("inc", "a");
3159 emitcode ("", "%05d$:", lbl->key+100);
3160 emitcode ("xch", "a,b");
3163 if (AOP_TYPE(right)==AOP_LIT) {
3164 /* AND literal negative */
3165 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3166 // two's complement for literal<0
3167 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3168 emitcode ("cpl", "a");
3169 emitcode ("inc", "a");
3172 lbl=newiTempLabel(NULL);
3173 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3174 // right side is negative, 8-bit two's complement
3175 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3176 emitcode ("cpl", "a");
3177 emitcode ("inc", "a");
3178 emitcode ("", "%05d$:", lbl->key+100);
3180 emitcode ("mul", "ab");
3182 lbl=newiTempLabel(NULL);
3183 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3184 // only ONE op was negative, we have to do a 8/16-bit two's complement
3185 emitcode ("cpl", "a"); // lsb
3187 emitcode ("inc", "a");
3189 emitcode ("add", "a,#1");
3190 emitcode ("xch", "a,b");
3191 emitcode ("cpl", "a"); // msb
3192 emitcode ("addc", "a,#0");
3193 emitcode ("xch", "a,b");
3196 emitcode ("", "%05d$:", lbl->key+100);
3197 aopPut (AOP (result), "a", 0);
3199 aopPut (AOP (result), "b", 1);
3203 /*-----------------------------------------------------------------*/
3204 /* genMult - generates code for multiplication */
3205 /*-----------------------------------------------------------------*/
3207 genMult (iCode * ic)
3209 operand *left = IC_LEFT (ic);
3210 operand *right = IC_RIGHT (ic);
3211 operand *result = IC_RESULT (ic);
3213 /* assign the amsops */
3214 aopOp (left, ic, FALSE);
3215 aopOp (right, ic, FALSE);
3216 aopOp (result, ic, TRUE);
3218 /* special cases first */
3220 if (AOP_TYPE (left) == AOP_CRY &&
3221 AOP_TYPE (right) == AOP_CRY)
3223 genMultbits (left, right, result);
3227 /* if both are of size == 1 */
3228 if (AOP_SIZE (left) == 1 &&
3229 AOP_SIZE (right) == 1)
3231 genMultOneByte (left, right, result);
3235 /* should have been converted to function call */
3239 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3240 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3241 freeAsmop (result, NULL, ic, TRUE);
3244 /*-----------------------------------------------------------------*/
3245 /* genDivbits :- division of bits */
3246 /*-----------------------------------------------------------------*/
3248 genDivbits (operand * left,
3255 /* the result must be bit */
3256 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3257 l = aopGet (AOP (left), 0, FALSE, FALSE);
3261 emitcode ("div", "ab");
3262 emitcode ("rrc", "a");
3263 aopPut (AOP (result), "c", 0);
3266 /*-----------------------------------------------------------------*/
3267 /* genDivOneByte : 8 bit division */
3268 /*-----------------------------------------------------------------*/
3270 genDivOneByte (operand * left,
3274 sym_link *opetype = operandType (result);
3279 size = AOP_SIZE (result) - 1;
3281 /* signed or unsigned */
3282 if (SPEC_USIGN (opetype))
3284 /* unsigned is easy */
3285 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3286 l = aopGet (AOP (left), 0, FALSE, FALSE);
3288 emitcode ("div", "ab");
3289 aopPut (AOP (result), "a", 0);
3291 aopPut (AOP (result), zero, offset++);
3295 /* signed is a little bit more difficult */
3297 /* save the signs of the operands */
3298 l = aopGet (AOP (left), 0, FALSE, FALSE);
3300 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3301 emitcode ("push", "acc"); /* save it on the stack */
3303 /* now sign adjust for both left & right */
3304 l = aopGet (AOP (right), 0, FALSE, FALSE);
3306 lbl = newiTempLabel (NULL);
3307 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3308 emitcode ("cpl", "a");
3309 emitcode ("inc", "a");
3310 emitcode ("", "%05d$:", (lbl->key + 100));
3311 emitcode ("mov", "b,a");
3313 /* sign adjust left side */
3314 l = aopGet (AOP (left), 0, FALSE, FALSE);
3317 lbl = newiTempLabel (NULL);
3318 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3319 emitcode ("cpl", "a");
3320 emitcode ("inc", "a");
3321 emitcode ("", "%05d$:", (lbl->key + 100));
3323 /* now the division */
3324 emitcode ("div", "ab");
3325 /* we are interested in the lower order
3327 emitcode ("mov", "b,a");
3328 lbl = newiTempLabel (NULL);
3329 emitcode ("pop", "acc");
3330 /* if there was an over flow we don't
3331 adjust the sign of the result */
3332 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3333 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3335 emitcode ("clr", "a");
3336 emitcode ("subb", "a,b");
3337 emitcode ("mov", "b,a");
3338 emitcode ("", "%05d$:", (lbl->key + 100));
3340 /* now we are done */
3341 aopPut (AOP (result), "b", 0);
3344 emitcode ("mov", "c,b.7");
3345 emitcode ("subb", "a,acc");
3348 aopPut (AOP (result), "a", offset++);
3352 /*-----------------------------------------------------------------*/
3353 /* genDiv - generates code for division */
3354 /*-----------------------------------------------------------------*/
3358 operand *left = IC_LEFT (ic);
3359 operand *right = IC_RIGHT (ic);
3360 operand *result = IC_RESULT (ic);
3362 /* assign the amsops */
3363 aopOp (left, ic, FALSE);
3364 aopOp (right, ic, FALSE);
3365 aopOp (result, ic, TRUE);
3367 /* special cases first */
3369 if (AOP_TYPE (left) == AOP_CRY &&
3370 AOP_TYPE (right) == AOP_CRY)
3372 genDivbits (left, right, result);
3376 /* if both are of size == 1 */
3377 if (AOP_SIZE (left) == 1 &&
3378 AOP_SIZE (right) == 1)
3380 genDivOneByte (left, right, result);
3384 /* should have been converted to function call */
3387 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3388 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3389 freeAsmop (result, NULL, ic, TRUE);
3392 /*-----------------------------------------------------------------*/
3393 /* genModbits :- modulus of bits */
3394 /*-----------------------------------------------------------------*/
3396 genModbits (operand * left,
3403 /* the result must be bit */
3404 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3405 l = aopGet (AOP (left), 0, FALSE, FALSE);
3409 emitcode ("div", "ab");
3410 emitcode ("mov", "a,b");
3411 emitcode ("rrc", "a");
3412 aopPut (AOP (result), "c", 0);
3415 /*-----------------------------------------------------------------*/
3416 /* genModOneByte : 8 bit modulus */
3417 /*-----------------------------------------------------------------*/
3419 genModOneByte (operand * left,
3423 sym_link *opetype = operandType (result);
3427 /* signed or unsigned */
3428 if (SPEC_USIGN (opetype))
3430 /* unsigned is easy */
3431 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3432 l = aopGet (AOP (left), 0, FALSE, FALSE);
3434 emitcode ("div", "ab");
3435 aopPut (AOP (result), "b", 0);
3439 /* signed is a little bit more difficult */
3441 /* save the signs of the operands */
3442 l = aopGet (AOP (left), 0, FALSE, FALSE);
3445 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3446 emitcode ("push", "acc"); /* save it on the stack */
3448 /* now sign adjust for both left & right */
3449 l = aopGet (AOP (right), 0, FALSE, FALSE);
3452 lbl = newiTempLabel (NULL);
3453 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3454 emitcode ("cpl", "a");
3455 emitcode ("inc", "a");
3456 emitcode ("", "%05d$:", (lbl->key + 100));
3457 emitcode ("mov", "b,a");
3459 /* sign adjust left side */
3460 l = aopGet (AOP (left), 0, FALSE, FALSE);
3463 lbl = newiTempLabel (NULL);
3464 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3465 emitcode ("cpl", "a");
3466 emitcode ("inc", "a");
3467 emitcode ("", "%05d$:", (lbl->key + 100));
3469 /* now the multiplication */
3470 emitcode ("div", "ab");
3471 /* we are interested in the lower order
3473 lbl = newiTempLabel (NULL);
3474 emitcode ("pop", "acc");
3475 /* if there was an over flow we don't
3476 adjust the sign of the result */
3477 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3478 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3480 emitcode ("clr", "a");
3481 emitcode ("subb", "a,b");
3482 emitcode ("mov", "b,a");
3483 emitcode ("", "%05d$:", (lbl->key + 100));
3485 /* now we are done */
3486 aopPut (AOP (result), "b", 0);
3490 /*-----------------------------------------------------------------*/
3491 /* genMod - generates code for division */
3492 /*-----------------------------------------------------------------*/
3496 operand *left = IC_LEFT (ic);
3497 operand *right = IC_RIGHT (ic);
3498 operand *result = IC_RESULT (ic);
3500 /* assign the amsops */
3501 aopOp (left, ic, FALSE);
3502 aopOp (right, ic, FALSE);
3503 aopOp (result, ic, TRUE);
3505 /* special cases first */
3507 if (AOP_TYPE (left) == AOP_CRY &&
3508 AOP_TYPE (right) == AOP_CRY)
3510 genModbits (left, right, result);
3514 /* if both are of size == 1 */
3515 if (AOP_SIZE (left) == 1 &&
3516 AOP_SIZE (right) == 1)
3518 genModOneByte (left, right, result);
3522 /* should have been converted to function call */
3526 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3527 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3528 freeAsmop (result, NULL, ic, TRUE);
3531 /*-----------------------------------------------------------------*/
3532 /* genIfxJump :- will create a jump depending on the ifx */
3533 /*-----------------------------------------------------------------*/
3535 genIfxJump (iCode * ic, char *jval)
3538 symbol *tlbl = newiTempLabel (NULL);
3541 /* if true label then we jump if condition
3545 jlbl = IC_TRUE (ic);
3546 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3547 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3551 /* false label is present */
3552 jlbl = IC_FALSE (ic);
3553 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3554 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3556 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3557 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3559 emitcode (inst, "%05d$", tlbl->key + 100);
3560 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3561 emitcode ("", "%05d$:", tlbl->key + 100);
3563 /* mark the icode as generated */
3567 /*-----------------------------------------------------------------*/
3568 /* genCmp :- greater or less than comparison */
3569 /*-----------------------------------------------------------------*/
3571 genCmp (operand * left, operand * right,
3572 operand * result, iCode * ifx, int sign, iCode *ic)
3574 int size, offset = 0;
3575 unsigned long lit = 0L;
3577 /* if left & right are bit variables */
3578 if (AOP_TYPE (left) == AOP_CRY &&
3579 AOP_TYPE (right) == AOP_CRY)
3581 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3582 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3586 /* subtract right from left if at the
3587 end the carry flag is set then we know that
3588 left is greater than right */
3589 size = max (AOP_SIZE (left), AOP_SIZE (right));
3591 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3592 if ((size == 1) && !sign &&
3593 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3595 symbol *lbl = newiTempLabel (NULL);
3596 emitcode ("cjne", "%s,%s,%05d$",
3597 aopGet (AOP (left), offset, FALSE, FALSE),
3598 aopGet (AOP (right), offset, FALSE, FALSE),
3600 emitcode ("", "%05d$:", lbl->key + 100);
3604 if (AOP_TYPE (right) == AOP_LIT)
3606 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3607 /* optimize if(x < 0) or if(x >= 0) */
3616 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3617 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3619 genIfxJump (ifx, "acc.7");
3623 emitcode ("rlc", "a");
3631 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3632 if (sign && size == 0)
3634 emitcode ("xrl", "a,#0x80");
3635 if (AOP_TYPE (right) == AOP_LIT)
3637 unsigned long lit = (unsigned long)
3638 floatFromVal (AOP (right)->aopu.aop_lit);
3639 emitcode ("subb", "a,#0x%02x",
3640 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3644 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3645 emitcode ("xrl", "b,#0x80");
3646 emitcode ("subb", "a,b");
3650 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3656 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3657 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3658 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3664 /* if the result is used in the next
3665 ifx conditional branch then generate
3666 code a little differently */
3668 genIfxJump (ifx, "c");
3671 /* leave the result in acc */
3675 /*-----------------------------------------------------------------*/
3676 /* genCmpGt :- greater than comparison */
3677 /*-----------------------------------------------------------------*/
3679 genCmpGt (iCode * ic, iCode * ifx)
3681 operand *left, *right, *result;
3682 sym_link *letype, *retype;
3685 left = IC_LEFT (ic);
3686 right = IC_RIGHT (ic);
3687 result = IC_RESULT (ic);
3689 letype = getSpec (operandType (left));
3690 retype = getSpec (operandType (right));
3691 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3692 /* assign the amsops */
3693 aopOp (left, ic, FALSE);
3694 aopOp (right, ic, FALSE);
3695 aopOp (result, ic, TRUE);
3697 genCmp (right, left, result, ifx, sign,ic);
3699 freeAsmop (result, NULL, ic, TRUE);
3702 /*-----------------------------------------------------------------*/
3703 /* genCmpLt - less than comparisons */
3704 /*-----------------------------------------------------------------*/
3706 genCmpLt (iCode * ic, iCode * ifx)
3708 operand *left, *right, *result;
3709 sym_link *letype, *retype;
3712 left = IC_LEFT (ic);
3713 right = IC_RIGHT (ic);
3714 result = IC_RESULT (ic);
3716 letype = getSpec (operandType (left));
3717 retype = getSpec (operandType (right));
3718 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3720 /* assign the amsops */
3721 aopOp (left, ic, FALSE);
3722 aopOp (right, ic, FALSE);
3723 aopOp (result, ic, TRUE);
3725 genCmp (left, right, result, ifx, sign,ic);
3727 freeAsmop (result, NULL, ic, TRUE);
3730 /*-----------------------------------------------------------------*/
3731 /* gencjneshort - compare and jump if not equal */
3732 /*-----------------------------------------------------------------*/
3734 gencjneshort (operand * left, operand * right, symbol * lbl)
3736 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3738 unsigned long lit = 0L;
3740 /* if the left side is a literal or
3741 if the right is in a pointer register and left
3743 if ((AOP_TYPE (left) == AOP_LIT) ||
3744 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3750 if (AOP_TYPE (right) == AOP_LIT)
3751 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3753 /* if the right side is a literal then anything goes */
3754 if (AOP_TYPE (right) == AOP_LIT &&
3755 AOP_TYPE (left) != AOP_DIR)
3759 emitcode ("cjne", "%s,%s,%05d$",
3760 aopGet (AOP (left), offset, FALSE, FALSE),
3761 aopGet (AOP (right), offset, FALSE, FALSE),
3767 /* if the right side is in a register or in direct space or
3768 if the left is a pointer register & right is not */
3769 else if (AOP_TYPE (right) == AOP_REG ||
3770 AOP_TYPE (right) == AOP_DIR ||
3771 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3772 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3776 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3777 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3778 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3779 emitcode ("jnz", "%05d$", lbl->key + 100);
3781 emitcode ("cjne", "a,%s,%05d$",
3782 aopGet (AOP (right), offset, FALSE, TRUE),
3789 /* right is a pointer reg need both a & b */
3792 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3793 if (strcmp (l, "b"))
3794 emitcode ("mov", "b,%s", l);
3795 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3796 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3802 /*-----------------------------------------------------------------*/
3803 /* gencjne - compare and jump if not equal */
3804 /*-----------------------------------------------------------------*/
3806 gencjne (operand * left, operand * right, symbol * lbl)
3808 symbol *tlbl = newiTempLabel (NULL);
3810 gencjneshort (left, right, lbl);
3812 emitcode ("mov", "a,%s", one);
3813 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3814 emitcode ("", "%05d$:", lbl->key + 100);
3815 emitcode ("clr", "a");
3816 emitcode ("", "%05d$:", tlbl->key + 100);
3819 /*-----------------------------------------------------------------*/
3820 /* genCmpEq - generates code for equal to */
3821 /*-----------------------------------------------------------------*/
3823 genCmpEq (iCode * ic, iCode * ifx)
3825 operand *left, *right, *result;
3827 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3828 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3829 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3831 /* if literal, literal on the right or
3832 if the right is in a pointer register and left
3834 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3835 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3837 operand *t = IC_RIGHT (ic);
3838 IC_RIGHT (ic) = IC_LEFT (ic);
3842 if (ifx && !AOP_SIZE (result))
3845 /* if they are both bit variables */
3846 if (AOP_TYPE (left) == AOP_CRY &&
3847 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3849 if (AOP_TYPE (right) == AOP_LIT)
3851 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3854 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3855 emitcode ("cpl", "c");
3859 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3863 emitcode ("clr", "c");
3865 /* AOP_TYPE(right) == AOP_CRY */
3869 symbol *lbl = newiTempLabel (NULL);
3870 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3871 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3872 emitcode ("cpl", "c");
3873 emitcode ("", "%05d$:", (lbl->key + 100));
3875 /* if true label then we jump if condition
3877 tlbl = newiTempLabel (NULL);
3880 emitcode ("jnc", "%05d$", tlbl->key + 100);
3881 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3885 emitcode ("jc", "%05d$", tlbl->key + 100);
3886 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3888 emitcode ("", "%05d$:", tlbl->key + 100);
3892 tlbl = newiTempLabel (NULL);
3893 gencjneshort (left, right, tlbl);
3896 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3897 emitcode ("", "%05d$:", tlbl->key + 100);
3901 symbol *lbl = newiTempLabel (NULL);
3902 emitcode ("sjmp", "%05d$", lbl->key + 100);
3903 emitcode ("", "%05d$:", tlbl->key + 100);
3904 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3905 emitcode ("", "%05d$:", lbl->key + 100);
3908 /* mark the icode as generated */
3913 /* if they are both bit variables */
3914 if (AOP_TYPE (left) == AOP_CRY &&
3915 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3917 if (AOP_TYPE (right) == AOP_LIT)
3919 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3922 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3923 emitcode ("cpl", "c");
3927 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3931 emitcode ("clr", "c");
3933 /* AOP_TYPE(right) == AOP_CRY */
3937 symbol *lbl = newiTempLabel (NULL);
3938 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3939 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3940 emitcode ("cpl", "c");
3941 emitcode ("", "%05d$:", (lbl->key + 100));
3944 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3951 genIfxJump (ifx, "c");
3954 /* if the result is used in an arithmetic operation
3955 then put the result in place */
3960 gencjne (left, right, newiTempLabel (NULL));
3961 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3963 aopPut (AOP (result), "a", 0);
3968 genIfxJump (ifx, "a");
3971 /* if the result is used in an arithmetic operation
3972 then put the result in place */
3973 if (AOP_TYPE (result) != AOP_CRY)
3975 /* leave the result in acc */
3979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3980 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981 freeAsmop (result, NULL, ic, TRUE);
3984 /*-----------------------------------------------------------------*/
3985 /* ifxForOp - returns the icode containing the ifx for operand */
3986 /*-----------------------------------------------------------------*/
3988 ifxForOp (operand * op, iCode * ic)
3990 /* if true symbol then needs to be assigned */
3991 if (IS_TRUE_SYMOP (op))
3994 /* if this has register type condition and
3995 the next instruction is ifx with the same operand
3996 and live to of the operand is upto the ifx only then */
3998 ic->next->op == IFX &&
3999 IC_COND (ic->next)->key == op->key &&
4000 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4006 /*-----------------------------------------------------------------*/
4007 /* hasInc - operand is incremented before any other use */
4008 /*-----------------------------------------------------------------*/
4010 hasInc (operand *op, iCode *ic)
4012 sym_link *type = operandType(op);
4013 sym_link *retype = getSpec (type);
4014 iCode *lic = ic->next;
4017 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4018 isize = getSize(type->next);
4020 /* if operand of the form op = op + <sizeof *op> */
4021 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4022 isOperandEqual(IC_RESULT(lic),op) &&
4023 isOperandLiteral(IC_RIGHT(lic)) &&
4024 operandLitValue(IC_RIGHT(lic)) == isize) {
4027 /* if the operand used or deffed */
4028 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4036 /*-----------------------------------------------------------------*/
4037 /* genAndOp - for && operation */
4038 /*-----------------------------------------------------------------*/
4040 genAndOp (iCode * ic)
4042 operand *left, *right, *result;
4045 /* note here that && operations that are in an
4046 if statement are taken away by backPatchLabels
4047 only those used in arthmetic operations remain */
4048 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4049 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4050 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4052 /* if both are bit variables */
4053 if (AOP_TYPE (left) == AOP_CRY &&
4054 AOP_TYPE (right) == AOP_CRY)
4056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4057 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4062 tlbl = newiTempLabel (NULL);
4064 emitcode ("jz", "%05d$", tlbl->key + 100);
4066 emitcode ("", "%05d$:", tlbl->key + 100);
4070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4071 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4072 freeAsmop (result, NULL, ic, TRUE);
4076 /*-----------------------------------------------------------------*/
4077 /* genOrOp - for || operation */
4078 /*-----------------------------------------------------------------*/
4080 genOrOp (iCode * ic)
4082 operand *left, *right, *result;
4085 /* note here that || operations that are in an
4086 if statement are taken away by backPatchLabels
4087 only those used in arthmetic operations remain */
4088 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4089 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4090 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4092 /* if both are bit variables */
4093 if (AOP_TYPE (left) == AOP_CRY &&
4094 AOP_TYPE (right) == AOP_CRY)
4096 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4097 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4102 tlbl = newiTempLabel (NULL);
4104 emitcode ("jnz", "%05d$", tlbl->key + 100);
4106 emitcode ("", "%05d$:", tlbl->key + 100);
4110 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4112 freeAsmop (result, NULL, ic, TRUE);
4115 /*-----------------------------------------------------------------*/
4116 /* isLiteralBit - test if lit == 2^n */
4117 /*-----------------------------------------------------------------*/
4119 isLiteralBit (unsigned long lit)
4121 unsigned long pw[32] =
4122 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4123 0x100L, 0x200L, 0x400L, 0x800L,
4124 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4125 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4126 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4127 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4128 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4131 for (idx = 0; idx < 32; idx++)
4137 /*-----------------------------------------------------------------*/
4138 /* continueIfTrue - */
4139 /*-----------------------------------------------------------------*/
4141 continueIfTrue (iCode * ic)
4144 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4148 /*-----------------------------------------------------------------*/
4150 /*-----------------------------------------------------------------*/
4152 jumpIfTrue (iCode * ic)
4155 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4159 /*-----------------------------------------------------------------*/
4160 /* jmpTrueOrFalse - */
4161 /*-----------------------------------------------------------------*/
4163 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4165 // ugly but optimized by peephole
4168 symbol *nlbl = newiTempLabel (NULL);
4169 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4170 emitcode ("", "%05d$:", tlbl->key + 100);
4171 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4172 emitcode ("", "%05d$:", nlbl->key + 100);
4176 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4177 emitcode ("", "%05d$:", tlbl->key + 100);
4182 /*-----------------------------------------------------------------*/
4183 /* genAnd - code for and */
4184 /*-----------------------------------------------------------------*/
4186 genAnd (iCode * ic, iCode * ifx)
4188 operand *left, *right, *result;
4189 int size, offset = 0;
4190 unsigned long lit = 0L;
4194 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4195 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4196 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4199 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4201 AOP_TYPE (left), AOP_TYPE (right));
4202 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4204 AOP_SIZE (left), AOP_SIZE (right));
4207 /* if left is a literal & right is not then exchange them */
4208 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4209 AOP_NEEDSACC (left))
4211 operand *tmp = right;
4216 /* if result = right then exchange them */
4217 if (sameRegs (AOP (result), AOP (right)))
4219 operand *tmp = right;
4224 /* if right is bit then exchange them */
4225 if (AOP_TYPE (right) == AOP_CRY &&
4226 AOP_TYPE (left) != AOP_CRY)
4228 operand *tmp = right;
4232 if (AOP_TYPE (right) == AOP_LIT)
4233 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4235 size = AOP_SIZE (result);
4238 // result = bit & yy;
4239 if (AOP_TYPE (left) == AOP_CRY)
4241 // c = bit & literal;
4242 if (AOP_TYPE (right) == AOP_LIT)
4246 if (size && sameRegs (AOP (result), AOP (left)))
4249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4254 if (size && (AOP_TYPE (result) == AOP_CRY))
4256 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4259 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4264 emitcode ("clr", "c");
4269 if (AOP_TYPE (right) == AOP_CRY)
4272 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4273 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4278 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4280 emitcode ("rrc", "a");
4281 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4289 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4290 genIfxJump (ifx, "c");
4294 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4295 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4296 if ((AOP_TYPE (right) == AOP_LIT) &&
4297 (AOP_TYPE (result) == AOP_CRY) &&
4298 (AOP_TYPE (left) != AOP_CRY))
4300 int posbit = isLiteralBit (lit);
4305 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4308 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4314 sprintf (buffer, "acc.%d", posbit & 0x07);
4315 genIfxJump (ifx, buffer);
4322 symbol *tlbl = newiTempLabel (NULL);
4323 int sizel = AOP_SIZE (left);
4325 emitcode ("setb", "c");
4328 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4330 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4332 if ((posbit = isLiteralBit (bytelit)) != 0)
4333 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4336 if (bytelit != 0x0FFL)
4337 emitcode ("anl", "a,%s",
4338 aopGet (AOP (right), offset, FALSE, TRUE));
4339 emitcode ("jnz", "%05d$", tlbl->key + 100);
4344 // bit = left & literal
4347 emitcode ("clr", "c");
4348 emitcode ("", "%05d$:", tlbl->key + 100);
4350 // if(left & literal)
4354 jmpTrueOrFalse (ifx, tlbl);
4362 /* if left is same as result */
4363 if (sameRegs (AOP (result), AOP (left)))
4365 for (; size--; offset++)
4367 if (AOP_TYPE (right) == AOP_LIT)
4369 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4371 else if (bytelit == 0)
4372 aopPut (AOP (result), zero, offset);
4373 else if (IS_AOP_PREG (result))
4375 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4376 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4377 aopPut (AOP (result), "a", offset);
4380 emitcode ("anl", "%s,%s",
4381 aopGet (AOP (left), offset, FALSE, TRUE),
4382 aopGet (AOP (right), offset, FALSE, FALSE));
4386 if (AOP_TYPE (left) == AOP_ACC)
4387 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4390 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4391 if (IS_AOP_PREG (result))
4393 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4394 aopPut (AOP (result), "a", offset);
4398 emitcode ("anl", "%s,a",
4399 aopGet (AOP (left), offset, FALSE, TRUE));
4406 // left & result in different registers
4407 if (AOP_TYPE (result) == AOP_CRY)
4410 // if(size), result in bit
4411 // if(!size && ifx), conditional oper: if(left & right)
4412 symbol *tlbl = newiTempLabel (NULL);
4413 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4415 emitcode ("setb", "c");
4418 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4419 emitcode ("anl", "a,%s",
4420 aopGet (AOP (left), offset, FALSE, FALSE));
4421 emitcode ("jnz", "%05d$", tlbl->key + 100);
4427 emitcode ("", "%05d$:", tlbl->key + 100);
4431 jmpTrueOrFalse (ifx, tlbl);
4435 for (; (size--); offset++)
4438 // result = left & right
4439 if (AOP_TYPE (right) == AOP_LIT)
4441 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4443 aopPut (AOP (result),
4444 aopGet (AOP (left), offset, FALSE, FALSE),
4448 else if (bytelit == 0)
4450 aopPut (AOP (result), zero, offset);
4454 // faster than result <- left, anl result,right
4455 // and better if result is SFR
4456 if (AOP_TYPE (left) == AOP_ACC)
4457 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4460 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4461 emitcode ("anl", "a,%s",
4462 aopGet (AOP (left), offset, FALSE, FALSE));
4464 aopPut (AOP (result), "a", offset);
4470 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (result, NULL, ic, TRUE);
4475 /*-----------------------------------------------------------------*/
4476 /* genOr - code for or */
4477 /*-----------------------------------------------------------------*/
4479 genOr (iCode * ic, iCode * ifx)
4481 operand *left, *right, *result;
4482 int size, offset = 0;
4483 unsigned long lit = 0L;
4485 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4486 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4487 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4490 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4492 AOP_TYPE (left), AOP_TYPE (right));
4493 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4495 AOP_SIZE (left), AOP_SIZE (right));
4498 /* if left is a literal & right is not then exchange them */
4499 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4500 AOP_NEEDSACC (left))
4502 operand *tmp = right;
4507 /* if result = right then exchange them */
4508 if (sameRegs (AOP (result), AOP (right)))
4510 operand *tmp = right;
4515 /* if right is bit then exchange them */
4516 if (AOP_TYPE (right) == AOP_CRY &&
4517 AOP_TYPE (left) != AOP_CRY)
4519 operand *tmp = right;
4523 if (AOP_TYPE (right) == AOP_LIT)
4524 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4526 size = AOP_SIZE (result);
4530 if (AOP_TYPE (left) == AOP_CRY)
4532 if (AOP_TYPE (right) == AOP_LIT)
4534 // c = bit & literal;
4537 // lit != 0 => result = 1
4538 if (AOP_TYPE (result) == AOP_CRY)
4541 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4543 continueIfTrue (ifx);
4546 emitcode ("setb", "c");
4550 // lit == 0 => result = left
4551 if (size && sameRegs (AOP (result), AOP (left)))
4553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4558 if (AOP_TYPE (right) == AOP_CRY)
4561 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4562 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4567 symbol *tlbl = newiTempLabel (NULL);
4568 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4569 emitcode ("setb", "c");
4570 emitcode ("jb", "%s,%05d$",
4571 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4573 emitcode ("jnz", "%05d$", tlbl->key + 100);
4574 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4576 jmpTrueOrFalse (ifx, tlbl);
4582 emitcode ("", "%05d$:", tlbl->key + 100);
4591 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4592 genIfxJump (ifx, "c");
4596 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4597 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4598 if ((AOP_TYPE (right) == AOP_LIT) &&
4599 (AOP_TYPE (result) == AOP_CRY) &&
4600 (AOP_TYPE (left) != AOP_CRY))
4606 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4608 continueIfTrue (ifx);
4613 // lit = 0, result = boolean(left)
4615 emitcode ("setb", "c");
4619 symbol *tlbl = newiTempLabel (NULL);
4620 emitcode ("jnz", "%05d$", tlbl->key + 100);
4622 emitcode ("", "%05d$:", tlbl->key + 100);
4626 genIfxJump (ifx, "a");
4634 /* if left is same as result */
4635 if (sameRegs (AOP (result), AOP (left)))
4637 for (; size--; offset++)
4639 if (AOP_TYPE (right) == AOP_LIT)
4641 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4643 else if (IS_AOP_PREG (left))
4645 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4646 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4647 aopPut (AOP (result), "a", offset);
4650 emitcode ("orl", "%s,%s",
4651 aopGet (AOP (left), offset, FALSE, TRUE),
4652 aopGet (AOP (right), offset, FALSE, FALSE));
4656 if (AOP_TYPE (left) == AOP_ACC)
4657 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4660 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4661 if (IS_AOP_PREG (left))
4663 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4664 aopPut (AOP (result), "a", offset);
4667 emitcode ("orl", "%s,a",
4668 aopGet (AOP (left), offset, FALSE, TRUE));
4675 // left & result in different registers
4676 if (AOP_TYPE (result) == AOP_CRY)
4679 // if(size), result in bit
4680 // if(!size && ifx), conditional oper: if(left | right)
4681 symbol *tlbl = newiTempLabel (NULL);
4682 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4684 emitcode ("setb", "c");
4687 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4688 emitcode ("orl", "a,%s",
4689 aopGet (AOP (left), offset, FALSE, FALSE));
4690 emitcode ("jnz", "%05d$", tlbl->key + 100);
4696 emitcode ("", "%05d$:", tlbl->key + 100);
4700 jmpTrueOrFalse (ifx, tlbl);
4703 for (; (size--); offset++)
4706 // result = left & right
4707 if (AOP_TYPE (right) == AOP_LIT)
4709 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4711 aopPut (AOP (result),
4712 aopGet (AOP (left), offset, FALSE, FALSE),
4717 // faster than result <- left, anl result,right
4718 // and better if result is SFR
4719 if (AOP_TYPE (left) == AOP_ACC)
4720 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4723 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4724 emitcode ("orl", "a,%s",
4725 aopGet (AOP (left), offset, FALSE, FALSE));
4727 aopPut (AOP (result), "a", offset);
4732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4733 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734 freeAsmop (result, NULL, ic, TRUE);
4737 /*-----------------------------------------------------------------*/
4738 /* genXor - code for xclusive or */
4739 /*-----------------------------------------------------------------*/
4741 genXor (iCode * ic, iCode * ifx)
4743 operand *left, *right, *result;
4744 int size, offset = 0;
4745 unsigned long lit = 0L;
4747 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4748 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4749 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4752 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4754 AOP_TYPE (left), AOP_TYPE (right));
4755 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4757 AOP_SIZE (left), AOP_SIZE (right));
4760 /* if left is a literal & right is not ||
4761 if left needs acc & right does not */
4762 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4763 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4765 operand *tmp = right;
4770 /* if result = right then exchange them */
4771 if (sameRegs (AOP (result), AOP (right)))
4773 operand *tmp = right;
4778 /* if right is bit then exchange them */
4779 if (AOP_TYPE (right) == AOP_CRY &&
4780 AOP_TYPE (left) != AOP_CRY)
4782 operand *tmp = right;
4786 if (AOP_TYPE (right) == AOP_LIT)
4787 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4789 size = AOP_SIZE (result);
4793 if (AOP_TYPE (left) == AOP_CRY)
4795 if (AOP_TYPE (right) == AOP_LIT)
4797 // c = bit & literal;
4800 // lit>>1 != 0 => result = 1
4801 if (AOP_TYPE (result) == AOP_CRY)
4804 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4806 continueIfTrue (ifx);
4809 emitcode ("setb", "c");
4816 // lit == 0, result = left
4817 if (size && sameRegs (AOP (result), AOP (left)))
4819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4823 // lit == 1, result = not(left)
4824 if (size && sameRegs (AOP (result), AOP (left)))
4826 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4831 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832 emitcode ("cpl", "c");
4841 symbol *tlbl = newiTempLabel (NULL);
4842 if (AOP_TYPE (right) == AOP_CRY)
4845 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4849 int sizer = AOP_SIZE (right);
4851 // if val>>1 != 0, result = 1
4852 emitcode ("setb", "c");
4855 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4857 // test the msb of the lsb
4858 emitcode ("anl", "a,#0xfe");
4859 emitcode ("jnz", "%05d$", tlbl->key + 100);
4863 emitcode ("rrc", "a");
4865 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4866 emitcode ("cpl", "c");
4867 emitcode ("", "%05d$:", (tlbl->key + 100));
4874 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4875 genIfxJump (ifx, "c");
4879 if (sameRegs (AOP (result), AOP (left)))
4881 /* if left is same as result */
4882 for (; size--; offset++)
4884 if (AOP_TYPE (right) == AOP_LIT)
4886 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4888 else if (IS_AOP_PREG (left))
4890 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4891 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4892 aopPut (AOP (result), "a", offset);
4895 emitcode ("xrl", "%s,%s",
4896 aopGet (AOP (left), offset, FALSE, TRUE),
4897 aopGet (AOP (right), offset, FALSE, FALSE));
4901 if (AOP_TYPE (left) == AOP_ACC)
4902 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4905 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4906 if (IS_AOP_PREG (left))
4908 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4909 aopPut (AOP (result), "a", offset);
4912 emitcode ("xrl", "%s,a",
4913 aopGet (AOP (left), offset, FALSE, TRUE));
4920 // left & result in different registers
4921 if (AOP_TYPE (result) == AOP_CRY)
4924 // if(size), result in bit
4925 // if(!size && ifx), conditional oper: if(left ^ right)
4926 symbol *tlbl = newiTempLabel (NULL);
4927 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4929 emitcode ("setb", "c");
4932 if ((AOP_TYPE (right) == AOP_LIT) &&
4933 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4935 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4939 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4940 emitcode ("xrl", "a,%s",
4941 aopGet (AOP (left), offset, FALSE, FALSE));
4943 emitcode ("jnz", "%05d$", tlbl->key + 100);
4949 emitcode ("", "%05d$:", tlbl->key + 100);
4953 jmpTrueOrFalse (ifx, tlbl);
4956 for (; (size--); offset++)
4959 // result = left & right
4960 if (AOP_TYPE (right) == AOP_LIT)
4962 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4964 aopPut (AOP (result),
4965 aopGet (AOP (left), offset, FALSE, FALSE),
4970 // faster than result <- left, anl result,right
4971 // and better if result is SFR
4972 if (AOP_TYPE (left) == AOP_ACC)
4973 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4976 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4977 emitcode ("xrl", "a,%s",
4978 aopGet (AOP (left), offset, FALSE, TRUE));
4980 aopPut (AOP (result), "a", offset);
4985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987 freeAsmop (result, NULL, ic, TRUE);
4990 /*-----------------------------------------------------------------*/
4991 /* genInline - write the inline code out */
4992 /*-----------------------------------------------------------------*/
4994 genInline (iCode * ic)
4996 char *buffer, *bp, *bp1;
4998 _G.inLine += (!options.asmpeep);
5000 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5001 strcpy (buffer, IC_INLINE (ic));
5003 /* emit each line as a code */
5028 /* emitcode("",buffer); */
5029 _G.inLine -= (!options.asmpeep);
5032 /*-----------------------------------------------------------------*/
5033 /* genRRC - rotate right with carry */
5034 /*-----------------------------------------------------------------*/
5038 operand *left, *result;
5039 int size, offset = 0;
5042 /* rotate right with carry */
5043 left = IC_LEFT (ic);
5044 result = IC_RESULT (ic);
5045 aopOp (left, ic, FALSE);
5046 aopOp (result, ic, FALSE);
5048 /* move it to the result */
5049 size = AOP_SIZE (result);
5054 l = aopGet (AOP (left), offset, FALSE, FALSE);
5056 emitcode ("rrc", "a");
5057 if (AOP_SIZE (result) > 1)
5058 aopPut (AOP (result), "a", offset--);
5060 /* now we need to put the carry into the
5061 highest order byte of the result */
5062 if (AOP_SIZE (result) > 1)
5064 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5067 emitcode ("mov", "acc.7,c");
5068 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5069 freeAsmop (left, NULL, ic, TRUE);
5070 freeAsmop (result, NULL, ic, TRUE);
5073 /*-----------------------------------------------------------------*/
5074 /* genRLC - generate code for rotate left with carry */
5075 /*-----------------------------------------------------------------*/
5079 operand *left, *result;
5080 int size, offset = 0;
5083 /* rotate right with carry */
5084 left = IC_LEFT (ic);
5085 result = IC_RESULT (ic);
5086 aopOp (left, ic, FALSE);
5087 aopOp (result, ic, FALSE);
5089 /* move it to the result */
5090 size = AOP_SIZE (result);
5094 l = aopGet (AOP (left), offset, FALSE, FALSE);
5096 emitcode ("add", "a,acc");
5097 if (AOP_SIZE (result) > 1)
5098 aopPut (AOP (result), "a", offset++);
5101 l = aopGet (AOP (left), offset, FALSE, FALSE);
5103 emitcode ("rlc", "a");
5104 if (AOP_SIZE (result) > 1)
5105 aopPut (AOP (result), "a", offset++);
5108 /* now we need to put the carry into the
5109 highest order byte of the result */
5110 if (AOP_SIZE (result) > 1)
5112 l = aopGet (AOP (result), 0, FALSE, FALSE);
5115 emitcode ("mov", "acc.0,c");
5116 aopPut (AOP (result), "a", 0);
5117 freeAsmop (left, NULL, ic, TRUE);
5118 freeAsmop (result, NULL, ic, TRUE);
5121 /*-----------------------------------------------------------------*/
5122 /* genGetHbit - generates code get highest order bit */
5123 /*-----------------------------------------------------------------*/
5125 genGetHbit (iCode * ic)
5127 operand *left, *result;
5128 left = IC_LEFT (ic);
5129 result = IC_RESULT (ic);
5130 aopOp (left, ic, FALSE);
5131 aopOp (result, ic, FALSE);
5133 /* get the highest order byte into a */
5134 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5135 if (AOP_TYPE (result) == AOP_CRY)
5137 emitcode ("rlc", "a");
5142 emitcode ("rl", "a");
5143 emitcode ("anl", "a,#0x01");
5148 freeAsmop (left, NULL, ic, TRUE);
5149 freeAsmop (result, NULL, ic, TRUE);
5152 /*-----------------------------------------------------------------*/
5153 /* AccRol - rotate left accumulator by known count */
5154 /*-----------------------------------------------------------------*/
5156 AccRol (int shCount)
5158 shCount &= 0x0007; // shCount : 0..7
5165 emitcode ("rl", "a");
5168 emitcode ("rl", "a");
5169 emitcode ("rl", "a");
5172 emitcode ("swap", "a");
5173 emitcode ("rr", "a");
5176 emitcode ("swap", "a");
5179 emitcode ("swap", "a");
5180 emitcode ("rl", "a");
5183 emitcode ("rr", "a");
5184 emitcode ("rr", "a");
5187 emitcode ("rr", "a");
5192 /*-----------------------------------------------------------------*/
5193 /* AccLsh - left shift accumulator by known count */
5194 /*-----------------------------------------------------------------*/
5196 AccLsh (int shCount)
5201 emitcode ("add", "a,acc");
5202 else if (shCount == 2)
5204 emitcode ("add", "a,acc");
5205 emitcode ("add", "a,acc");
5209 /* rotate left accumulator */
5211 /* and kill the lower order bits */
5212 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5217 /*-----------------------------------------------------------------*/
5218 /* AccRsh - right shift accumulator by known count */
5219 /*-----------------------------------------------------------------*/
5221 AccRsh (int shCount)
5228 emitcode ("rrc", "a");
5232 /* rotate right accumulator */
5233 AccRol (8 - shCount);
5234 /* and kill the higher order bits */
5235 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5240 /*-----------------------------------------------------------------*/
5241 /* AccSRsh - signed right shift accumulator by known count */
5242 /*-----------------------------------------------------------------*/
5244 AccSRsh (int shCount)
5251 emitcode ("mov", "c,acc.7");
5252 emitcode ("rrc", "a");
5254 else if (shCount == 2)
5256 emitcode ("mov", "c,acc.7");
5257 emitcode ("rrc", "a");
5258 emitcode ("mov", "c,acc.7");
5259 emitcode ("rrc", "a");
5263 tlbl = newiTempLabel (NULL);
5264 /* rotate right accumulator */
5265 AccRol (8 - shCount);
5266 /* and kill the higher order bits */
5267 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5268 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5269 emitcode ("orl", "a,#0x%02x",
5270 (unsigned char) ~SRMask[shCount]);
5271 emitcode ("", "%05d$:", tlbl->key + 100);
5276 /*-----------------------------------------------------------------*/
5277 /* shiftR1Left2Result - shift right one byte from left to result */
5278 /*-----------------------------------------------------------------*/
5280 shiftR1Left2Result (operand * left, int offl,
5281 operand * result, int offr,
5282 int shCount, int sign)
5284 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5285 /* shift right accumulator */
5290 aopPut (AOP (result), "a", offr);
5293 /*-----------------------------------------------------------------*/
5294 /* shiftL1Left2Result - shift left one byte from left to result */
5295 /*-----------------------------------------------------------------*/
5297 shiftL1Left2Result (operand * left, int offl,
5298 operand * result, int offr, int shCount)
5301 l = aopGet (AOP (left), offl, FALSE, FALSE);
5303 /* shift left accumulator */
5305 aopPut (AOP (result), "a", offr);
5308 /*-----------------------------------------------------------------*/
5309 /* movLeft2Result - move byte from left to result */
5310 /*-----------------------------------------------------------------*/
5312 movLeft2Result (operand * left, int offl,
5313 operand * result, int offr, int sign)
5316 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5318 l = aopGet (AOP (left), offl, FALSE, FALSE);
5320 if (*l == '@' && (IS_AOP_PREG (result)))
5322 emitcode ("mov", "a,%s", l);
5323 aopPut (AOP (result), "a", offr);
5328 aopPut (AOP (result), l, offr);
5331 /* MSB sign in acc.7 ! */
5332 if (getDataSize (left) == offl + 1)
5334 emitcode ("mov", "a,%s", l);
5335 aopPut (AOP (result), "a", offr);
5342 /*-----------------------------------------------------------------*/
5343 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5344 /*-----------------------------------------------------------------*/
5348 emitcode ("rrc", "a");
5349 emitcode ("xch", "a,%s", x);
5350 emitcode ("rrc", "a");
5351 emitcode ("xch", "a,%s", x);
5354 /*-----------------------------------------------------------------*/
5355 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5356 /*-----------------------------------------------------------------*/
5360 emitcode ("xch", "a,%s", x);
5361 emitcode ("rlc", "a");
5362 emitcode ("xch", "a,%s", x);
5363 emitcode ("rlc", "a");
5366 /*-----------------------------------------------------------------*/
5367 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5368 /*-----------------------------------------------------------------*/
5372 emitcode ("xch", "a,%s", x);
5373 emitcode ("add", "a,acc");
5374 emitcode ("xch", "a,%s", x);
5375 emitcode ("rlc", "a");
5378 /*-----------------------------------------------------------------*/
5379 /* AccAXLsh - left shift a:x by known count (0..7) */
5380 /*-----------------------------------------------------------------*/
5382 AccAXLsh (char *x, int shCount)
5397 case 5: // AAAAABBB:CCCCCDDD
5399 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5401 emitcode ("anl", "a,#0x%02x",
5402 SLMask[shCount]); // BBB00000:CCCCCDDD
5404 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5406 AccRol (shCount); // DDDCCCCC:BBB00000
5408 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5410 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5412 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5414 emitcode ("anl", "a,#0x%02x",
5415 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5417 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5419 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5422 case 6: // AAAAAABB:CCCCCCDD
5423 emitcode ("anl", "a,#0x%02x",
5424 SRMask[shCount]); // 000000BB:CCCCCCDD
5425 emitcode ("mov", "c,acc.0"); // c = B
5426 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5428 AccAXRrl1 (x); // BCCCCCCD:D000000B
5429 AccAXRrl1 (x); // BBCCCCCC:DD000000
5431 emitcode("rrc","a");
5432 emitcode("xch","a,%s", x);
5433 emitcode("rrc","a");
5434 emitcode("mov","c,acc.0"); //<< get correct bit
5435 emitcode("xch","a,%s", x);
5437 emitcode("rrc","a");
5438 emitcode("xch","a,%s", x);
5439 emitcode("rrc","a");
5440 emitcode("xch","a,%s", x);
5443 case 7: // a:x <<= 7
5445 emitcode ("anl", "a,#0x%02x",
5446 SRMask[shCount]); // 0000000B:CCCCCCCD
5448 emitcode ("mov", "c,acc.0"); // c = B
5450 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5452 AccAXRrl1 (x); // BCCCCCCC:D0000000
5460 /*-----------------------------------------------------------------*/
5461 /* AccAXRsh - right shift a:x known count (0..7) */
5462 /*-----------------------------------------------------------------*/
5464 AccAXRsh (char *x, int shCount)
5472 AccAXRrl1 (x); // 0->a:x
5477 AccAXRrl1 (x); // 0->a:x
5480 AccAXRrl1 (x); // 0->a:x
5485 case 5: // AAAAABBB:CCCCCDDD = a:x
5487 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5489 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5491 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5493 emitcode ("anl", "a,#0x%02x",
5494 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5496 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5498 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5500 emitcode ("anl", "a,#0x%02x",
5501 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5503 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5505 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5507 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5510 case 6: // AABBBBBB:CCDDDDDD
5512 emitcode ("mov", "c,acc.7");
5513 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5515 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5517 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5519 emitcode ("anl", "a,#0x%02x",
5520 SRMask[shCount]); // 000000AA:BBBBBBCC
5523 case 7: // ABBBBBBB:CDDDDDDD
5525 emitcode ("mov", "c,acc.7"); // c = A
5527 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5529 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5531 emitcode ("anl", "a,#0x%02x",
5532 SRMask[shCount]); // 0000000A:BBBBBBBC
5540 /*-----------------------------------------------------------------*/
5541 /* AccAXRshS - right shift signed a:x known count (0..7) */
5542 /*-----------------------------------------------------------------*/
5544 AccAXRshS (char *x, int shCount)
5552 emitcode ("mov", "c,acc.7");
5553 AccAXRrl1 (x); // s->a:x
5557 emitcode ("mov", "c,acc.7");
5558 AccAXRrl1 (x); // s->a:x
5560 emitcode ("mov", "c,acc.7");
5561 AccAXRrl1 (x); // s->a:x
5566 case 5: // AAAAABBB:CCCCCDDD = a:x
5568 tlbl = newiTempLabel (NULL);
5569 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5571 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5573 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5575 emitcode ("anl", "a,#0x%02x",
5576 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5578 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5580 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5582 emitcode ("anl", "a,#0x%02x",
5583 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5585 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5587 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5589 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5591 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5592 emitcode ("orl", "a,#0x%02x",
5593 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5595 emitcode ("", "%05d$:", tlbl->key + 100);
5596 break; // SSSSAAAA:BBBCCCCC
5598 case 6: // AABBBBBB:CCDDDDDD
5600 tlbl = newiTempLabel (NULL);
5601 emitcode ("mov", "c,acc.7");
5602 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5604 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5606 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5608 emitcode ("anl", "a,#0x%02x",
5609 SRMask[shCount]); // 000000AA:BBBBBBCC
5611 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5612 emitcode ("orl", "a,#0x%02x",
5613 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5615 emitcode ("", "%05d$:", tlbl->key + 100);
5617 case 7: // ABBBBBBB:CDDDDDDD
5619 tlbl = newiTempLabel (NULL);
5620 emitcode ("mov", "c,acc.7"); // c = A
5622 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5624 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5626 emitcode ("anl", "a,#0x%02x",
5627 SRMask[shCount]); // 0000000A:BBBBBBBC
5629 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5630 emitcode ("orl", "a,#0x%02x",
5631 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5633 emitcode ("", "%05d$:", tlbl->key + 100);
5640 /*-----------------------------------------------------------------*/
5641 /* shiftL2Left2Result - shift left two bytes from left to result */
5642 /*-----------------------------------------------------------------*/
5644 shiftL2Left2Result (operand * left, int offl,
5645 operand * result, int offr, int shCount)
5647 if (sameRegs (AOP (result), AOP (left)) &&
5648 ((offl + MSB16) == offr))
5650 /* don't crash result[offr] */
5651 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5652 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5656 movLeft2Result (left, offl, result, offr, 0);
5657 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5659 /* ax << shCount (x = lsb(result)) */
5660 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5661 aopPut (AOP (result), "a", offr + MSB16);
5665 /*-----------------------------------------------------------------*/
5666 /* shiftR2Left2Result - shift right two bytes from left to result */
5667 /*-----------------------------------------------------------------*/
5669 shiftR2Left2Result (operand * left, int offl,
5670 operand * result, int offr,
5671 int shCount, int sign)
5673 if (sameRegs (AOP (result), AOP (left)) &&
5674 ((offl + MSB16) == offr))
5676 /* don't crash result[offr] */
5677 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5678 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5682 movLeft2Result (left, offl, result, offr, 0);
5683 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5685 /* a:x >> shCount (x = lsb(result)) */
5687 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5689 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5690 if (getDataSize (result) > 1)
5691 aopPut (AOP (result), "a", offr + MSB16);
5694 /*-----------------------------------------------------------------*/
5695 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5696 /*-----------------------------------------------------------------*/
5698 shiftLLeftOrResult (operand * left, int offl,
5699 operand * result, int offr, int shCount)
5701 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5702 /* shift left accumulator */
5704 /* or with result */
5705 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5706 /* back to result */
5707 aopPut (AOP (result), "a", offr);
5710 /*-----------------------------------------------------------------*/
5711 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5712 /*-----------------------------------------------------------------*/
5714 shiftRLeftOrResult (operand * left, int offl,
5715 operand * result, int offr, int shCount)
5717 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5718 /* shift right accumulator */
5720 /* or with result */
5721 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5722 /* back to result */
5723 aopPut (AOP (result), "a", offr);
5726 /*-----------------------------------------------------------------*/
5727 /* genlshOne - left shift a one byte quantity by known count */
5728 /*-----------------------------------------------------------------*/
5730 genlshOne (operand * result, operand * left, int shCount)
5732 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5735 /*-----------------------------------------------------------------*/
5736 /* genlshTwo - left shift two bytes by known amount != 0 */
5737 /*-----------------------------------------------------------------*/
5739 genlshTwo (operand * result, operand * left, int shCount)
5743 size = getDataSize (result);
5745 /* if shCount >= 8 */
5753 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5755 movLeft2Result (left, LSB, result, MSB16, 0);
5757 aopPut (AOP (result), zero, LSB);
5760 /* 1 <= shCount <= 7 */
5764 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5766 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5770 /*-----------------------------------------------------------------*/
5771 /* shiftLLong - shift left one long from left to result */
5772 /* offl = LSB or MSB16 */
5773 /*-----------------------------------------------------------------*/
5775 shiftLLong (operand * left, operand * result, int offr)
5778 int size = AOP_SIZE (result);
5780 if (size >= LSB + offr)
5782 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5784 emitcode ("add", "a,acc");
5785 if (sameRegs (AOP (left), AOP (result)) &&
5786 size >= MSB16 + offr && offr != LSB)
5787 emitcode ("xch", "a,%s",
5788 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5790 aopPut (AOP (result), "a", LSB + offr);
5793 if (size >= MSB16 + offr)
5795 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5797 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5800 emitcode ("rlc", "a");
5801 if (sameRegs (AOP (left), AOP (result)) &&
5802 size >= MSB24 + offr && offr != LSB)
5803 emitcode ("xch", "a,%s",
5804 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5806 aopPut (AOP (result), "a", MSB16 + offr);
5809 if (size >= MSB24 + offr)
5811 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5813 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5816 emitcode ("rlc", "a");
5817 if (sameRegs (AOP (left), AOP (result)) &&
5818 size >= MSB32 + offr && offr != LSB)
5819 emitcode ("xch", "a,%s",
5820 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5822 aopPut (AOP (result), "a", MSB24 + offr);
5825 if (size > MSB32 + offr)
5827 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5829 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5832 emitcode ("rlc", "a");
5833 aopPut (AOP (result), "a", MSB32 + offr);
5836 aopPut (AOP (result), zero, LSB);
5839 /*-----------------------------------------------------------------*/
5840 /* genlshFour - shift four byte by a known amount != 0 */
5841 /*-----------------------------------------------------------------*/
5843 genlshFour (operand * result, operand * left, int shCount)
5847 size = AOP_SIZE (result);
5849 /* if shifting more that 3 bytes */
5854 /* lowest order of left goes to the highest
5855 order of the destination */
5856 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5858 movLeft2Result (left, LSB, result, MSB32, 0);
5859 aopPut (AOP (result), zero, LSB);
5860 aopPut (AOP (result), zero, MSB16);
5861 aopPut (AOP (result), zero, MSB24);
5865 /* more than two bytes */
5866 else if (shCount >= 16)
5868 /* lower order two bytes goes to higher order two bytes */
5870 /* if some more remaining */
5872 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5875 movLeft2Result (left, MSB16, result, MSB32, 0);
5876 movLeft2Result (left, LSB, result, MSB24, 0);
5878 aopPut (AOP (result), zero, MSB16);
5879 aopPut (AOP (result), zero, LSB);
5883 /* if more than 1 byte */
5884 else if (shCount >= 8)
5886 /* lower order three bytes goes to higher order three bytes */
5891 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5893 movLeft2Result (left, LSB, result, MSB16, 0);
5899 movLeft2Result (left, MSB24, result, MSB32, 0);
5900 movLeft2Result (left, MSB16, result, MSB24, 0);
5901 movLeft2Result (left, LSB, result, MSB16, 0);
5902 aopPut (AOP (result), zero, LSB);
5904 else if (shCount == 1)
5905 shiftLLong (left, result, MSB16);
5908 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5909 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5910 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5911 aopPut (AOP (result), zero, LSB);
5916 /* 1 <= shCount <= 7 */
5917 else if (shCount <= 2)
5919 shiftLLong (left, result, LSB);
5921 shiftLLong (result, result, LSB);
5923 /* 3 <= shCount <= 7, optimize */
5926 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5927 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5928 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5932 /*-----------------------------------------------------------------*/
5933 /* genLeftShiftLiteral - left shifting by known count */
5934 /*-----------------------------------------------------------------*/
5936 genLeftShiftLiteral (operand * left,
5941 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5944 freeAsmop (right, NULL, ic, TRUE);
5946 aopOp (left, ic, FALSE);
5947 aopOp (result, ic, FALSE);
5949 size = getSize (operandType (result));
5952 emitcode ("; shift left ", "result %d, left %d", size,
5956 /* I suppose that the left size >= result size */
5961 movLeft2Result (left, size, result, size, 0);
5965 else if (shCount >= (size * 8))
5967 aopPut (AOP (result), zero, size);
5973 genlshOne (result, left, shCount);
5978 genlshTwo (result, left, shCount);
5982 genlshFour (result, left, shCount);
5986 freeAsmop (left, NULL, ic, TRUE);
5987 freeAsmop (result, NULL, ic, TRUE);
5990 /*-----------------------------------------------------------------*/
5991 /* genLeftShift - generates code for left shifting */
5992 /*-----------------------------------------------------------------*/
5994 genLeftShift (iCode * ic)
5996 operand *left, *right, *result;
5999 symbol *tlbl, *tlbl1;
6001 right = IC_RIGHT (ic);
6002 left = IC_LEFT (ic);
6003 result = IC_RESULT (ic);
6005 aopOp (right, ic, FALSE);
6007 /* if the shift count is known then do it
6008 as efficiently as possible */
6009 if (AOP_TYPE (right) == AOP_LIT)
6011 genLeftShiftLiteral (left, right, result, ic);
6015 /* shift count is unknown then we have to form
6016 a loop get the loop count in B : Note: we take
6017 only the lower order byte since shifting
6018 more that 32 bits make no sense anyway, ( the
6019 largest size of an object can be only 32 bits ) */
6021 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6022 emitcode ("inc", "b");
6023 freeAsmop (right, NULL, ic, TRUE);
6024 aopOp (left, ic, FALSE);
6025 aopOp (result, ic, FALSE);
6027 /* now move the left to the result if they are not the
6029 if (!sameRegs (AOP (left), AOP (result)) &&
6030 AOP_SIZE (result) > 1)
6033 size = AOP_SIZE (result);
6037 l = aopGet (AOP (left), offset, FALSE, TRUE);
6038 if (*l == '@' && (IS_AOP_PREG (result)))
6041 emitcode ("mov", "a,%s", l);
6042 aopPut (AOP (result), "a", offset);
6045 aopPut (AOP (result), l, offset);
6050 tlbl = newiTempLabel (NULL);
6051 size = AOP_SIZE (result);
6053 tlbl1 = newiTempLabel (NULL);
6055 /* if it is only one byte then */
6058 symbol *tlbl1 = newiTempLabel (NULL);
6060 l = aopGet (AOP (left), 0, FALSE, FALSE);
6062 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6063 emitcode ("", "%05d$:", tlbl->key + 100);
6064 emitcode ("add", "a,acc");
6065 emitcode ("", "%05d$:", tlbl1->key + 100);
6066 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6067 aopPut (AOP (result), "a", 0);
6071 reAdjustPreg (AOP (result));
6073 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6074 emitcode ("", "%05d$:", tlbl->key + 100);
6075 l = aopGet (AOP (result), offset, FALSE, FALSE);
6077 emitcode ("add", "a,acc");
6078 aopPut (AOP (result), "a", offset++);
6081 l = aopGet (AOP (result), offset, FALSE, FALSE);
6083 emitcode ("rlc", "a");
6084 aopPut (AOP (result), "a", offset++);
6086 reAdjustPreg (AOP (result));
6088 emitcode ("", "%05d$:", tlbl1->key + 100);
6089 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6091 freeAsmop (left, NULL, ic, TRUE);
6092 freeAsmop (result, NULL, ic, TRUE);
6095 /*-----------------------------------------------------------------*/
6096 /* genrshOne - right shift a one byte quantity by known count */
6097 /*-----------------------------------------------------------------*/
6099 genrshOne (operand * result, operand * left,
6100 int shCount, int sign)
6102 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6105 /*-----------------------------------------------------------------*/
6106 /* genrshTwo - right shift two bytes by known amount != 0 */
6107 /*-----------------------------------------------------------------*/
6109 genrshTwo (operand * result, operand * left,
6110 int shCount, int sign)
6112 /* if shCount >= 8 */
6117 shiftR1Left2Result (left, MSB16, result, LSB,
6120 movLeft2Result (left, MSB16, result, LSB, sign);
6121 addSign (result, MSB16, sign);
6124 /* 1 <= shCount <= 7 */
6126 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6129 /*-----------------------------------------------------------------*/
6130 /* shiftRLong - shift right one long from left to result */
6131 /* offl = LSB or MSB16 */
6132 /*-----------------------------------------------------------------*/
6134 shiftRLong (operand * left, int offl,
6135 operand * result, int sign)
6138 emitcode ("clr", "c");
6139 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6141 emitcode ("mov", "c,acc.7");
6142 emitcode ("rrc", "a");
6143 aopPut (AOP (result), "a", MSB32 - offl);
6145 /* add sign of "a" */
6146 addSign (result, MSB32, sign);
6148 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6149 emitcode ("rrc", "a");
6150 aopPut (AOP (result), "a", MSB24 - offl);
6152 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6153 emitcode ("rrc", "a");
6154 aopPut (AOP (result), "a", MSB16 - offl);
6158 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6159 emitcode ("rrc", "a");
6160 aopPut (AOP (result), "a", LSB);
6164 /*-----------------------------------------------------------------*/
6165 /* genrshFour - shift four byte by a known amount != 0 */
6166 /*-----------------------------------------------------------------*/
6168 genrshFour (operand * result, operand * left,
6169 int shCount, int sign)
6171 /* if shifting more that 3 bytes */
6176 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6178 movLeft2Result (left, MSB32, result, LSB, sign);
6179 addSign (result, MSB16, sign);
6181 else if (shCount >= 16)
6185 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6188 movLeft2Result (left, MSB24, result, LSB, 0);
6189 movLeft2Result (left, MSB32, result, MSB16, sign);
6191 addSign (result, MSB24, sign);
6193 else if (shCount >= 8)
6197 shiftRLong (left, MSB16, result, sign);
6198 else if (shCount == 0)
6200 movLeft2Result (left, MSB16, result, LSB, 0);
6201 movLeft2Result (left, MSB24, result, MSB16, 0);
6202 movLeft2Result (left, MSB32, result, MSB24, sign);
6203 addSign (result, MSB32, sign);
6207 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6208 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6209 /* the last shift is signed */
6210 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6211 addSign (result, MSB32, sign);
6215 { /* 1 <= shCount <= 7 */
6218 shiftRLong (left, LSB, result, sign);
6220 shiftRLong (result, LSB, result, sign);
6224 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6225 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6226 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6231 /*-----------------------------------------------------------------*/
6232 /* genRightShiftLiteral - right shifting by known count */
6233 /*-----------------------------------------------------------------*/
6235 genRightShiftLiteral (operand * left,
6241 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6244 freeAsmop (right, NULL, ic, TRUE);
6246 aopOp (left, ic, FALSE);
6247 aopOp (result, ic, FALSE);
6250 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6254 size = getDataSize (left);
6255 /* test the LEFT size !!! */
6257 /* I suppose that the left size >= result size */
6260 size = getDataSize (result);
6262 movLeft2Result (left, size, result, size, 0);
6265 else if (shCount >= (size * 8))
6268 /* get sign in acc.7 */
6269 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6270 addSign (result, LSB, sign);
6277 genrshOne (result, left, shCount, sign);
6281 genrshTwo (result, left, shCount, sign);
6285 genrshFour (result, left, shCount, sign);
6291 freeAsmop (left, NULL, ic, TRUE);
6292 freeAsmop (result, NULL, ic, TRUE);
6296 /*-----------------------------------------------------------------*/
6297 /* genSignedRightShift - right shift of signed number */
6298 /*-----------------------------------------------------------------*/
6300 genSignedRightShift (iCode * ic)
6302 operand *right, *left, *result;
6305 symbol *tlbl, *tlbl1;
6307 /* we do it the hard way put the shift count in b
6308 and loop thru preserving the sign */
6310 right = IC_RIGHT (ic);
6311 left = IC_LEFT (ic);
6312 result = IC_RESULT (ic);
6314 aopOp (right, ic, FALSE);
6317 if (AOP_TYPE (right) == AOP_LIT)
6319 genRightShiftLiteral (left, right, result, ic, 1);
6322 /* shift count is unknown then we have to form
6323 a loop get the loop count in B : Note: we take
6324 only the lower order byte since shifting
6325 more that 32 bits make no sense anyway, ( the
6326 largest size of an object can be only 32 bits ) */
6328 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6329 emitcode ("inc", "b");
6330 freeAsmop (right, NULL, ic, TRUE);
6331 aopOp (left, ic, FALSE);
6332 aopOp (result, ic, FALSE);
6334 /* now move the left to the result if they are not the
6336 if (!sameRegs (AOP (left), AOP (result)) &&
6337 AOP_SIZE (result) > 1)
6340 size = AOP_SIZE (result);
6344 l = aopGet (AOP (left), offset, FALSE, TRUE);
6345 if (*l == '@' && IS_AOP_PREG (result))
6348 emitcode ("mov", "a,%s", l);
6349 aopPut (AOP (result), "a", offset);
6352 aopPut (AOP (result), l, offset);
6357 /* mov the highest order bit to OVR */
6358 tlbl = newiTempLabel (NULL);
6359 tlbl1 = newiTempLabel (NULL);
6361 size = AOP_SIZE (result);
6363 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6364 emitcode ("rlc", "a");
6365 emitcode ("mov", "ov,c");
6366 /* if it is only one byte then */
6369 l = aopGet (AOP (left), 0, FALSE, FALSE);
6371 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6372 emitcode ("", "%05d$:", tlbl->key + 100);
6373 emitcode ("mov", "c,ov");
6374 emitcode ("rrc", "a");
6375 emitcode ("", "%05d$:", tlbl1->key + 100);
6376 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6377 aopPut (AOP (result), "a", 0);
6381 reAdjustPreg (AOP (result));
6382 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6383 emitcode ("", "%05d$:", tlbl->key + 100);
6384 emitcode ("mov", "c,ov");
6387 l = aopGet (AOP (result), offset, FALSE, FALSE);
6389 emitcode ("rrc", "a");
6390 aopPut (AOP (result), "a", offset--);
6392 reAdjustPreg (AOP (result));
6393 emitcode ("", "%05d$:", tlbl1->key + 100);
6394 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6397 freeAsmop (left, NULL, ic, TRUE);
6398 freeAsmop (result, NULL, ic, TRUE);
6401 /*-----------------------------------------------------------------*/
6402 /* genRightShift - generate code for right shifting */
6403 /*-----------------------------------------------------------------*/
6405 genRightShift (iCode * ic)
6407 operand *right, *left, *result;
6411 symbol *tlbl, *tlbl1;
6413 /* if signed then we do it the hard way preserve the
6414 sign bit moving it inwards */
6415 retype = getSpec (operandType (IC_RESULT (ic)));
6417 if (!SPEC_USIGN (retype))
6419 genSignedRightShift (ic);
6423 /* signed & unsigned types are treated the same : i.e. the
6424 signed is NOT propagated inwards : quoting from the
6425 ANSI - standard : "for E1 >> E2, is equivalent to division
6426 by 2**E2 if unsigned or if it has a non-negative value,
6427 otherwise the result is implementation defined ", MY definition
6428 is that the sign does not get propagated */
6430 right = IC_RIGHT (ic);
6431 left = IC_LEFT (ic);
6432 result = IC_RESULT (ic);
6434 aopOp (right, ic, FALSE);
6436 /* if the shift count is known then do it
6437 as efficiently as possible */
6438 if (AOP_TYPE (right) == AOP_LIT)
6440 genRightShiftLiteral (left, right, result, ic, 0);
6444 /* shift count is unknown then we have to form
6445 a loop get the loop count in B : Note: we take
6446 only the lower order byte since shifting
6447 more that 32 bits make no sense anyway, ( the
6448 largest size of an object can be only 32 bits ) */
6450 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6451 emitcode ("inc", "b");
6452 freeAsmop (right, NULL, ic, TRUE);
6453 aopOp (left, ic, FALSE);
6454 aopOp (result, ic, FALSE);
6456 /* now move the left to the result if they are not the
6458 if (!sameRegs (AOP (left), AOP (result)) &&
6459 AOP_SIZE (result) > 1)
6462 size = AOP_SIZE (result);
6466 l = aopGet (AOP (left), offset, FALSE, TRUE);
6467 if (*l == '@' && IS_AOP_PREG (result))
6470 emitcode ("mov", "a,%s", l);
6471 aopPut (AOP (result), "a", offset);
6474 aopPut (AOP (result), l, offset);
6479 tlbl = newiTempLabel (NULL);
6480 tlbl1 = newiTempLabel (NULL);
6481 size = AOP_SIZE (result);
6484 /* if it is only one byte then */
6487 l = aopGet (AOP (left), 0, FALSE, FALSE);
6489 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6490 emitcode ("", "%05d$:", tlbl->key + 100);
6492 emitcode ("rrc", "a");
6493 emitcode ("", "%05d$:", tlbl1->key + 100);
6494 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6495 aopPut (AOP (result), "a", 0);
6499 reAdjustPreg (AOP (result));
6500 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6501 emitcode ("", "%05d$:", tlbl->key + 100);
6505 l = aopGet (AOP (result), offset, FALSE, FALSE);
6507 emitcode ("rrc", "a");
6508 aopPut (AOP (result), "a", offset--);
6510 reAdjustPreg (AOP (result));
6512 emitcode ("", "%05d$:", tlbl1->key + 100);
6513 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6516 freeAsmop (left, NULL, ic, TRUE);
6517 freeAsmop (result, NULL, ic, TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* genUnpackBits - generates code for unpacking bits */
6522 /*-----------------------------------------------------------------*/
6524 genUnpackBits (operand * result, char *rname, int ptype)
6532 etype = getSpec (operandType (result));
6533 rsize = getSize (operandType (result));
6534 /* read the first byte */
6540 emitcode ("mov", "a,@%s", rname);
6544 emitcode ("movx", "a,@%s", rname);
6548 emitcode ("movx", "a,@dptr");
6552 emitcode ("clr", "a");
6553 emitcode ("movc", "a,%s", "@a+dptr");
6557 emitcode ("lcall", "__gptrget");
6561 rlen = SPEC_BLEN (etype);
6563 /* if we have bitdisplacement then it fits */
6564 /* into this byte completely or if length is */
6565 /* less than a byte */
6566 if ((shCnt = SPEC_BSTR (etype)) ||
6567 (SPEC_BLEN (etype) <= 8))
6570 /* shift right acc */
6573 emitcode ("anl", "a,#0x%02x",
6574 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6575 aopPut (AOP (result), "a", offset++);
6579 /* bit field did not fit in a byte */
6580 aopPut (AOP (result), "a", offset++);
6589 emitcode ("inc", "%s", rname);
6590 emitcode ("mov", "a,@%s", rname);
6594 emitcode ("inc", "%s", rname);
6595 emitcode ("movx", "a,@%s", rname);
6599 emitcode ("inc", "dptr");
6600 emitcode ("movx", "a,@dptr");
6604 emitcode ("clr", "a");
6605 emitcode ("inc", "dptr");
6606 emitcode ("movc", "a", "@a+dptr");
6610 emitcode ("inc", "dptr");
6611 emitcode ("lcall", "__gptrget");
6616 /* if we are done */
6620 aopPut (AOP (result), "a", offset++);
6626 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6628 aopPut (AOP (result), "a", offset++);
6636 aopPut (AOP (result), zero, offset++);
6642 /*-----------------------------------------------------------------*/
6643 /* genDataPointerGet - generates code when ptr offset is known */
6644 /*-----------------------------------------------------------------*/
6646 genDataPointerGet (operand * left,
6652 int size, offset = 0;
6653 aopOp (result, ic, TRUE);
6655 /* get the string representation of the name */
6656 l = aopGet (AOP (left), 0, FALSE, TRUE);
6657 size = AOP_SIZE (result);
6661 sprintf (buffer, "(%s + %d)", l + 1, offset);
6663 sprintf (buffer, "%s", l + 1);
6664 aopPut (AOP (result), buffer, offset++);
6667 freeAsmop (left, NULL, ic, TRUE);
6668 freeAsmop (result, NULL, ic, TRUE);
6671 /*-----------------------------------------------------------------*/
6672 /* genNearPointerGet - emitcode for near pointer fetch */
6673 /*-----------------------------------------------------------------*/
6675 genNearPointerGet (operand * left,
6683 sym_link *rtype, *retype;
6684 sym_link *ltype = operandType (left);
6687 rtype = operandType (result);
6688 retype = getSpec (rtype);
6690 aopOp (left, ic, FALSE);
6692 /* if left is rematerialisable and
6693 result is not bit variable type and
6694 the left is pointer to data space i.e
6695 lower 128 bytes of space */
6696 if (AOP_TYPE (left) == AOP_IMMD &&
6697 !IS_BITVAR (retype) &&
6698 DCL_TYPE (ltype) == POINTER)
6700 genDataPointerGet (left, result, ic);
6704 /* if the value is already in a pointer register
6705 then don't need anything more */
6706 if (!AOP_INPREG (AOP (left)))
6708 /* otherwise get a free pointer register */
6710 preg = getFreePtr (ic, &aop, FALSE);
6711 emitcode ("mov", "%s,%s",
6713 aopGet (AOP (left), 0, FALSE, TRUE));
6717 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6719 aopOp (result, ic, FALSE);
6721 /* if bitfield then unpack the bits */
6722 if (IS_BITVAR (retype))
6723 genUnpackBits (result, rname, POINTER);
6726 /* we have can just get the values */
6727 int size = AOP_SIZE (result);
6732 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6735 emitcode ("mov", "a,@%s", rname);
6736 aopPut (AOP (result), "a", offset);
6740 sprintf (buffer, "@%s", rname);
6741 aopPut (AOP (result), buffer, offset);
6745 emitcode ("inc", "%s", rname);
6749 /* now some housekeeping stuff */
6750 if (aop) /* we had to allocate for this iCode */
6752 if (pi) { /* post increment present */
6753 aopPut(AOP ( left ),rname,0);
6755 freeAsmop (NULL, aop, ic, TRUE);
6759 /* we did not allocate which means left
6760 already in a pointer register, then
6761 if size > 0 && this could be used again
6762 we have to point it back to where it
6764 if ((AOP_SIZE (result) > 1 &&
6765 !OP_SYMBOL (left)->remat &&
6766 (OP_SYMBOL (left)->liveTo > ic->seq ||
6770 int size = AOP_SIZE (result) - 1;
6772 emitcode ("dec", "%s", rname);
6777 freeAsmop (left, NULL, ic, TRUE);
6778 freeAsmop (result, NULL, ic, TRUE);
6779 if (pi) pi->generated = 1;
6782 /*-----------------------------------------------------------------*/
6783 /* genPagedPointerGet - emitcode for paged pointer fetch */
6784 /*-----------------------------------------------------------------*/
6786 genPagedPointerGet (operand * left,
6794 sym_link *rtype, *retype;
6796 rtype = operandType (result);
6797 retype = getSpec (rtype);
6799 aopOp (left, ic, FALSE);
6801 /* if the value is already in a pointer register
6802 then don't need anything more */
6803 if (!AOP_INPREG (AOP (left)))
6805 /* otherwise get a free pointer register */
6807 preg = getFreePtr (ic, &aop, FALSE);
6808 emitcode ("mov", "%s,%s",
6810 aopGet (AOP (left), 0, FALSE, TRUE));
6814 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6816 aopOp (result, ic, FALSE);
6818 /* if bitfield then unpack the bits */
6819 if (IS_BITVAR (retype))
6820 genUnpackBits (result, rname, PPOINTER);
6823 /* we have can just get the values */
6824 int size = AOP_SIZE (result);
6830 emitcode ("movx", "a,@%s", rname);
6831 aopPut (AOP (result), "a", offset);
6836 emitcode ("inc", "%s", rname);
6840 /* now some housekeeping stuff */
6841 if (aop) /* we had to allocate for this iCode */
6843 if (pi) aopPut ( AOP (left), rname, 0);
6844 freeAsmop (NULL, aop, ic, TRUE);
6848 /* we did not allocate which means left
6849 already in a pointer register, then
6850 if size > 0 && this could be used again
6851 we have to point it back to where it
6853 if ((AOP_SIZE (result) > 1 &&
6854 !OP_SYMBOL (left)->remat &&
6855 (OP_SYMBOL (left)->liveTo > ic->seq ||
6859 int size = AOP_SIZE (result) - 1;
6861 emitcode ("dec", "%s", rname);
6866 freeAsmop (left, NULL, ic, TRUE);
6867 freeAsmop (result, NULL, ic, TRUE);
6868 if (pi) pi->generated = 1;
6872 /*-----------------------------------------------------------------*/
6873 /* genFarPointerGet - gget value from far space */
6874 /*-----------------------------------------------------------------*/
6876 genFarPointerGet (operand * left,
6877 operand * result, iCode * ic, iCode * pi)
6880 sym_link *retype = getSpec (operandType (result));
6882 aopOp (left, ic, FALSE);
6884 /* if the operand is already in dptr
6885 then we do nothing else we move the value to dptr */
6886 if (AOP_TYPE (left) != AOP_STR)
6888 /* if this is remateriazable */
6889 if (AOP_TYPE (left) == AOP_IMMD)
6890 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6892 { /* we need to get it byte by byte */
6893 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6894 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6897 /* so dptr know contains the address */
6898 aopOp (result, ic, FALSE);
6900 /* if bit then unpack */
6901 if (IS_BITVAR (retype))
6902 genUnpackBits (result, "dptr", FPOINTER);
6905 size = AOP_SIZE (result);
6910 emitcode ("movx", "a,@dptr");
6911 aopPut (AOP (result), "a", offset++);
6913 emitcode ("inc", "dptr");
6917 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6918 aopPut ( AOP (left), "dpl", 0);
6919 aopPut ( AOP (left), "dph", 1);
6922 freeAsmop (left, NULL, ic, TRUE);
6923 freeAsmop (result, NULL, ic, TRUE);
6926 /*-----------------------------------------------------------------*/
6927 /* genCodePointerGet - gget value from code space */
6928 /*-----------------------------------------------------------------*/
6930 genCodePointerGet (operand * left,
6931 operand * result, iCode * ic, iCode *pi)
6934 sym_link *retype = getSpec (operandType (result));
6936 aopOp (left, ic, FALSE);
6938 /* if the operand is already in dptr
6939 then we do nothing else we move the value to dptr */
6940 if (AOP_TYPE (left) != AOP_STR)
6942 /* if this is remateriazable */
6943 if (AOP_TYPE (left) == AOP_IMMD)
6944 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6946 { /* we need to get it byte by byte */
6947 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6948 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6951 /* so dptr know contains the address */
6952 aopOp (result, ic, FALSE);
6954 /* if bit then unpack */
6955 if (IS_BITVAR (retype))
6956 genUnpackBits (result, "dptr", CPOINTER);
6959 size = AOP_SIZE (result);
6964 emitcode ("clr", "a");
6965 emitcode ("movc", "a,@a+dptr");
6966 aopPut (AOP (result), "a", offset++);
6968 emitcode ("inc", "dptr");
6972 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6973 aopPut ( AOP (left), "dpl", 0);
6974 aopPut ( AOP (left), "dph", 1);
6977 freeAsmop (left, NULL, ic, TRUE);
6978 freeAsmop (result, NULL, ic, TRUE);
6981 /*-----------------------------------------------------------------*/
6982 /* genGenPointerGet - gget value from generic pointer space */
6983 /*-----------------------------------------------------------------*/
6985 genGenPointerGet (operand * left,
6986 operand * result, iCode * ic, iCode *pi)
6989 sym_link *retype = getSpec (operandType (result));
6991 aopOp (left, ic, FALSE);
6993 /* if the operand is already in dptr
6994 then we do nothing else we move the value to dptr */
6995 if (AOP_TYPE (left) != AOP_STR)
6997 /* if this is remateriazable */
6998 if (AOP_TYPE (left) == AOP_IMMD)
7000 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7001 emitcode ("mov", "b,#%d", pointerCode (retype));
7004 { /* we need to get it byte by byte */
7005 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7006 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7007 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7010 /* so dptr know contains the address */
7011 aopOp (result, ic, FALSE);
7013 /* if bit then unpack */
7014 if (IS_BITVAR (retype))
7015 genUnpackBits (result, "dptr", GPOINTER);
7018 size = AOP_SIZE (result);
7023 emitcode ("lcall", "__gptrget");
7024 aopPut (AOP (result), "a", offset++);
7026 emitcode ("inc", "dptr");
7030 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7031 aopPut ( AOP (left), "dpl", 0);
7032 aopPut ( AOP (left), "dph", 1);
7035 freeAsmop (left, NULL, ic, TRUE);
7036 freeAsmop (result, NULL, ic, TRUE);
7039 /*-----------------------------------------------------------------*/
7040 /* genPointerGet - generate code for pointer get */
7041 /*-----------------------------------------------------------------*/
7043 genPointerGet (iCode * ic, iCode *pi)
7045 operand *left, *result;
7046 sym_link *type, *etype;
7049 left = IC_LEFT (ic);
7050 result = IC_RESULT (ic);
7052 /* depending on the type of pointer we need to
7053 move it to the correct pointer register */
7054 type = operandType (left);
7055 etype = getSpec (type);
7056 /* if left is of type of pointer then it is simple */
7057 if (IS_PTR (type) && !IS_FUNC (type->next))
7058 p_type = DCL_TYPE (type);
7061 /* we have to go by the storage class */
7062 p_type = PTR_TYPE (SPEC_OCLS (etype));
7065 /* now that we have the pointer type we assign
7066 the pointer values */
7072 genNearPointerGet (left, result, ic, pi);
7076 genPagedPointerGet (left, result, ic, pi);
7080 genFarPointerGet (left, result, ic, pi);
7084 genCodePointerGet (left, result, ic, pi);
7088 genGenPointerGet (left, result, ic, pi);
7094 /*-----------------------------------------------------------------*/
7095 /* genPackBits - generates code for packed bit storage */
7096 /*-----------------------------------------------------------------*/
7098 genPackBits (sym_link * etype,
7100 char *rname, int p_type)
7108 blen = SPEC_BLEN (etype);
7109 bstr = SPEC_BSTR (etype);
7111 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7114 /* if the bit lenth is less than or */
7115 /* it exactly fits a byte then */
7116 if (SPEC_BLEN (etype) <= 8)
7118 shCount = SPEC_BSTR (etype);
7120 /* shift left acc */
7123 if (SPEC_BLEN (etype) < 8)
7124 { /* if smaller than a byte */
7130 emitcode ("mov", "b,a");
7131 emitcode ("mov", "a,@%s", rname);
7135 emitcode ("mov", "b,a");
7136 emitcode ("movx", "a,@dptr");
7140 emitcode ("push", "b");
7141 emitcode ("push", "acc");
7142 emitcode ("lcall", "__gptrget");
7143 emitcode ("pop", "b");
7147 emitcode ("anl", "a,#0x%02x", (unsigned char)
7148 ((unsigned char) (0xFF << (blen + bstr)) |
7149 (unsigned char) (0xFF >> (8 - bstr))));
7150 emitcode ("orl", "a,b");
7151 if (p_type == GPOINTER)
7152 emitcode ("pop", "b");
7159 emitcode ("mov", "@%s,a", rname);
7163 emitcode ("movx", "@dptr,a");
7167 emitcode ("lcall", "__gptrput");
7172 if (SPEC_BLEN (etype) <= 8)
7175 emitcode ("inc", "%s", rname);
7176 rLen = SPEC_BLEN (etype);
7178 /* now generate for lengths greater than one byte */
7182 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7194 emitcode ("mov", "@%s,a", rname);
7197 emitcode ("mov", "@%s,%s", rname, l);
7202 emitcode ("movx", "@dptr,a");
7207 emitcode ("lcall", "__gptrput");
7210 emitcode ("inc", "%s", rname);
7215 /* last last was not complete */
7218 /* save the byte & read byte */
7222 emitcode ("mov", "b,a");
7223 emitcode ("mov", "a,@%s", rname);
7227 emitcode ("mov", "b,a");
7228 emitcode ("movx", "a,@dptr");
7232 emitcode ("push", "b");
7233 emitcode ("push", "acc");
7234 emitcode ("lcall", "__gptrget");
7235 emitcode ("pop", "b");
7239 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7240 emitcode ("orl", "a,b");
7243 if (p_type == GPOINTER)
7244 emitcode ("pop", "b");
7250 emitcode ("mov", "@%s,a", rname);
7254 emitcode ("movx", "@dptr,a");
7258 emitcode ("lcall", "__gptrput");
7262 /*-----------------------------------------------------------------*/
7263 /* genDataPointerSet - remat pointer to data space */
7264 /*-----------------------------------------------------------------*/
7266 genDataPointerSet (operand * right,
7270 int size, offset = 0;
7271 char *l, buffer[256];
7273 aopOp (right, ic, FALSE);
7275 l = aopGet (AOP (result), 0, FALSE, TRUE);
7276 size = AOP_SIZE (right);
7280 sprintf (buffer, "(%s + %d)", l + 1, offset);
7282 sprintf (buffer, "%s", l + 1);
7283 emitcode ("mov", "%s,%s", buffer,
7284 aopGet (AOP (right), offset++, FALSE, FALSE));
7287 freeAsmop (right, NULL, ic, TRUE);
7288 freeAsmop (result, NULL, ic, TRUE);
7291 /*-----------------------------------------------------------------*/
7292 /* genNearPointerSet - emitcode for near pointer put */
7293 /*-----------------------------------------------------------------*/
7295 genNearPointerSet (operand * right,
7303 sym_link *retype, *letype;
7304 sym_link *ptype = operandType (result);
7306 retype = getSpec (operandType (right));
7307 letype = getSpec (ptype);
7308 aopOp (result, ic, FALSE);
7310 /* if the result is rematerializable &
7311 in data space & not a bit variable */
7312 if (AOP_TYPE (result) == AOP_IMMD &&
7313 DCL_TYPE (ptype) == POINTER &&
7314 !IS_BITVAR (retype) &&
7315 !IS_BITVAR (letype))
7317 genDataPointerSet (right, result, ic);
7321 /* if the value is already in a pointer register
7322 then don't need anything more */
7323 if (!AOP_INPREG (AOP (result)))
7325 /* otherwise get a free pointer register */
7327 preg = getFreePtr (ic, &aop, FALSE);
7328 emitcode ("mov", "%s,%s",
7330 aopGet (AOP (result), 0, FALSE, TRUE));
7334 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7336 aopOp (right, ic, FALSE);
7338 /* if bitfield then unpack the bits */
7339 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7340 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7343 /* we have can just get the values */
7344 int size = AOP_SIZE (right);
7349 l = aopGet (AOP (right), offset, FALSE, TRUE);
7353 emitcode ("mov", "@%s,a", rname);
7356 emitcode ("mov", "@%s,%s", rname, l);
7358 emitcode ("inc", "%s", rname);
7363 /* now some housekeeping stuff */
7364 if (aop) /* we had to allocate for this iCode */
7366 if (pi) aopPut (AOP (result),rname,0);
7367 freeAsmop (NULL, aop, ic, TRUE);
7371 /* we did not allocate which means left
7372 already in a pointer register, then
7373 if size > 0 && this could be used again
7374 we have to point it back to where it
7376 if ((AOP_SIZE (right) > 1 &&
7377 !OP_SYMBOL (result)->remat &&
7378 (OP_SYMBOL (result)->liveTo > ic->seq ||
7382 int size = AOP_SIZE (right) - 1;
7384 emitcode ("dec", "%s", rname);
7389 if (pi) pi->generated = 1;
7390 freeAsmop (result, NULL, ic, TRUE);
7391 freeAsmop (right, NULL, ic, TRUE);
7394 /*-----------------------------------------------------------------*/
7395 /* genPagedPointerSet - emitcode for Paged pointer put */
7396 /*-----------------------------------------------------------------*/
7398 genPagedPointerSet (operand * right,
7406 sym_link *retype, *letype;
7408 retype = getSpec (operandType (right));
7409 letype = getSpec (operandType (result));
7411 aopOp (result, ic, FALSE);
7413 /* if the value is already in a pointer register
7414 then don't need anything more */
7415 if (!AOP_INPREG (AOP (result)))
7417 /* otherwise get a free pointer register */
7419 preg = getFreePtr (ic, &aop, FALSE);
7420 emitcode ("mov", "%s,%s",
7422 aopGet (AOP (result), 0, FALSE, TRUE));
7426 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7428 aopOp (right, ic, FALSE);
7430 /* if bitfield then unpack the bits */
7431 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7432 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7435 /* we have can just get the values */
7436 int size = AOP_SIZE (right);
7441 l = aopGet (AOP (right), offset, FALSE, TRUE);
7444 emitcode ("movx", "@%s,a", rname);
7447 emitcode ("inc", "%s", rname);
7453 /* now some housekeeping stuff */
7454 if (aop) /* we had to allocate for this iCode */
7456 if (pi) aopPut (AOP (result),rname,0);
7457 freeAsmop (NULL, aop, ic, TRUE);
7461 /* we did not allocate which means left
7462 already in a pointer register, then
7463 if size > 0 && this could be used again
7464 we have to point it back to where it
7466 if (AOP_SIZE (right) > 1 &&
7467 !OP_SYMBOL (result)->remat &&
7468 (OP_SYMBOL (result)->liveTo > ic->seq ||
7471 int size = AOP_SIZE (right) - 1;
7473 emitcode ("dec", "%s", rname);
7478 if (pi) pi->generated = 1;
7479 freeAsmop (result, NULL, ic, TRUE);
7480 freeAsmop (right, NULL, ic, TRUE);
7485 /*-----------------------------------------------------------------*/
7486 /* genFarPointerSet - set value from far space */
7487 /*-----------------------------------------------------------------*/
7489 genFarPointerSet (operand * right,
7490 operand * result, iCode * ic, iCode * pi)
7493 sym_link *retype = getSpec (operandType (right));
7494 sym_link *letype = getSpec (operandType (result));
7495 aopOp (result, ic, FALSE);
7497 /* if the operand is already in dptr
7498 then we do nothing else we move the value to dptr */
7499 if (AOP_TYPE (result) != AOP_STR)
7501 /* if this is remateriazable */
7502 if (AOP_TYPE (result) == AOP_IMMD)
7503 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7505 { /* we need to get it byte by byte */
7506 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7507 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7510 /* so dptr know contains the address */
7511 aopOp (right, ic, FALSE);
7513 /* if bit then unpack */
7514 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7515 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7518 size = AOP_SIZE (right);
7523 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7525 emitcode ("movx", "@dptr,a");
7527 emitcode ("inc", "dptr");
7530 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7531 aopPut (AOP(result),"dpl",0);
7532 aopPut (AOP(result),"dph",1);
7535 freeAsmop (result, NULL, ic, TRUE);
7536 freeAsmop (right, NULL, ic, TRUE);
7539 /*-----------------------------------------------------------------*/
7540 /* genGenPointerSet - set value from generic pointer space */
7541 /*-----------------------------------------------------------------*/
7543 genGenPointerSet (operand * right,
7544 operand * result, iCode * ic, iCode * pi)
7547 sym_link *retype = getSpec (operandType (right));
7548 sym_link *letype = getSpec (operandType (result));
7550 aopOp (result, ic, FALSE);
7552 /* if the operand is already in dptr
7553 then we do nothing else we move the value to dptr */
7554 if (AOP_TYPE (result) != AOP_STR)
7556 /* if this is remateriazable */
7557 if (AOP_TYPE (result) == AOP_IMMD)
7559 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7560 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7563 { /* we need to get it byte by byte */
7564 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7565 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7566 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7569 /* so dptr know contains the address */
7570 aopOp (right, ic, FALSE);
7572 /* if bit then unpack */
7573 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7574 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7577 size = AOP_SIZE (right);
7582 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7584 emitcode ("lcall", "__gptrput");
7586 emitcode ("inc", "dptr");
7590 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7591 aopPut (AOP(result),"dpl",0);
7592 aopPut (AOP(result),"dph",1);
7595 freeAsmop (result, NULL, ic, TRUE);
7596 freeAsmop (right, NULL, ic, TRUE);
7599 /*-----------------------------------------------------------------*/
7600 /* genPointerSet - stores the value into a pointer location */
7601 /*-----------------------------------------------------------------*/
7603 genPointerSet (iCode * ic, iCode *pi)
7605 operand *right, *result;
7606 sym_link *type, *etype;
7609 right = IC_RIGHT (ic);
7610 result = IC_RESULT (ic);
7612 /* depending on the type of pointer we need to
7613 move it to the correct pointer register */
7614 type = operandType (result);
7615 etype = getSpec (type);
7616 /* if left is of type of pointer then it is simple */
7617 if (IS_PTR (type) && !IS_FUNC (type->next))
7619 p_type = DCL_TYPE (type);
7623 /* we have to go by the storage class */
7624 p_type = PTR_TYPE (SPEC_OCLS (etype));
7627 /* now that we have the pointer type we assign
7628 the pointer values */
7634 genNearPointerSet (right, result, ic, pi);
7638 genPagedPointerSet (right, result, ic, pi);
7642 genFarPointerSet (right, result, ic, pi);
7646 genGenPointerSet (right, result, ic, pi);
7652 /*-----------------------------------------------------------------*/
7653 /* genIfx - generate code for Ifx statement */
7654 /*-----------------------------------------------------------------*/
7656 genIfx (iCode * ic, iCode * popIc)
7658 operand *cond = IC_COND (ic);
7661 aopOp (cond, ic, FALSE);
7663 /* get the value into acc */
7664 if (AOP_TYPE (cond) != AOP_CRY)
7668 /* the result is now in the accumulator */
7669 freeAsmop (cond, NULL, ic, TRUE);
7671 /* if there was something to be popped then do it */
7675 /* if the condition is a bit variable */
7676 if (isbit && IS_ITEMP (cond) &&
7678 genIfxJump (ic, SPIL_LOC (cond)->rname);
7679 else if (isbit && !IS_ITEMP (cond))
7680 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7682 genIfxJump (ic, "a");
7687 /*-----------------------------------------------------------------*/
7688 /* genAddrOf - generates code for address of */
7689 /*-----------------------------------------------------------------*/
7691 genAddrOf (iCode * ic)
7693 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7696 aopOp (IC_RESULT (ic), ic, FALSE);
7698 /* if the operand is on the stack then we
7699 need to get the stack offset of this
7703 /* if it has an offset then we need to compute
7707 emitcode ("mov", "a,_bp");
7708 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7709 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7713 /* we can just move _bp */
7714 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7716 /* fill the result with zero */
7717 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7722 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7728 /* object not on stack then we need the name */
7729 size = AOP_SIZE (IC_RESULT (ic));
7734 char s[SDCC_NAME_MAX];
7736 sprintf (s, "#(%s >> %d)",
7740 sprintf (s, "#%s", sym->rname);
7741 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7745 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7749 /*-----------------------------------------------------------------*/
7750 /* genFarFarAssign - assignment when both are in far space */
7751 /*-----------------------------------------------------------------*/
7753 genFarFarAssign (operand * result, operand * right, iCode * ic)
7755 int size = AOP_SIZE (right);
7758 /* first push the right side on to the stack */
7761 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7763 emitcode ("push", "acc");
7766 freeAsmop (right, NULL, ic, FALSE);
7767 /* now assign DPTR to result */
7768 aopOp (result, ic, FALSE);
7769 size = AOP_SIZE (result);
7772 emitcode ("pop", "acc");
7773 aopPut (AOP (result), "a", --offset);
7775 freeAsmop (result, NULL, ic, FALSE);
7779 /*-----------------------------------------------------------------*/
7780 /* genAssign - generate code for assignment */
7781 /*-----------------------------------------------------------------*/
7783 genAssign (iCode * ic)
7785 operand *result, *right;
7787 unsigned long lit = 0L;
7789 result = IC_RESULT (ic);
7790 right = IC_RIGHT (ic);
7792 /* if they are the same */
7793 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7796 aopOp (right, ic, FALSE);
7798 /* special case both in far space */
7799 if (AOP_TYPE (right) == AOP_DPTR &&
7800 IS_TRUE_SYMOP (result) &&
7801 isOperandInFarSpace (result))
7804 genFarFarAssign (result, right, ic);
7808 aopOp (result, ic, TRUE);
7810 /* if they are the same registers */
7811 if (sameRegs (AOP (right), AOP (result)))
7814 /* if the result is a bit */
7815 if (AOP_TYPE (result) == AOP_CRY)
7818 /* if the right size is a literal then
7819 we know what the value is */
7820 if (AOP_TYPE (right) == AOP_LIT)
7822 if (((int) operandLitValue (right)))
7823 aopPut (AOP (result), one, 0);
7825 aopPut (AOP (result), zero, 0);
7829 /* the right is also a bit variable */
7830 if (AOP_TYPE (right) == AOP_CRY)
7832 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7833 aopPut (AOP (result), "c", 0);
7839 aopPut (AOP (result), "a", 0);
7843 /* bit variables done */
7845 size = AOP_SIZE (result);
7847 if (AOP_TYPE (right) == AOP_LIT)
7848 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7850 (AOP_TYPE (result) != AOP_REG) &&
7851 (AOP_TYPE (right) == AOP_LIT) &&
7852 !IS_FLOAT (operandType (right)) &&
7855 emitcode ("clr", "a");
7858 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7859 aopPut (AOP (result), "a", size);
7861 aopPut (AOP (result),
7862 aopGet (AOP (right), size, FALSE, FALSE),
7870 aopPut (AOP (result),
7871 aopGet (AOP (right), offset, FALSE, FALSE),
7878 freeAsmop (right, NULL, ic, TRUE);
7879 freeAsmop (result, NULL, ic, TRUE);
7882 /*-----------------------------------------------------------------*/
7883 /* genJumpTab - genrates code for jump table */
7884 /*-----------------------------------------------------------------*/
7886 genJumpTab (iCode * ic)
7891 aopOp (IC_JTCOND (ic), ic, FALSE);
7892 /* get the condition into accumulator */
7893 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7895 /* multiply by three */
7896 emitcode ("add", "a,acc");
7897 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7898 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7900 jtab = newiTempLabel (NULL);
7901 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7902 emitcode ("jmp", "@a+dptr");
7903 emitcode ("", "%05d$:", jtab->key + 100);
7904 /* now generate the jump labels */
7905 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7906 jtab = setNextItem (IC_JTLABELS (ic)))
7907 emitcode ("ljmp", "%05d$", jtab->key + 100);
7911 /*-----------------------------------------------------------------*/
7912 /* genCast - gen code for casting */
7913 /*-----------------------------------------------------------------*/
7915 genCast (iCode * ic)
7917 operand *result = IC_RESULT (ic);
7918 sym_link *ctype = operandType (IC_LEFT (ic));
7919 sym_link *rtype = operandType (IC_RIGHT (ic));
7920 operand *right = IC_RIGHT (ic);
7923 /* if they are equivalent then do nothing */
7924 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7927 aopOp (right, ic, FALSE);
7928 aopOp (result, ic, FALSE);
7930 /* if the result is a bit */
7931 if (AOP_TYPE (result) == AOP_CRY)
7933 /* if the right size is a literal then
7934 we know what the value is */
7935 if (AOP_TYPE (right) == AOP_LIT)
7937 if (((int) operandLitValue (right)))
7938 aopPut (AOP (result), one, 0);
7940 aopPut (AOP (result), zero, 0);
7945 /* the right is also a bit variable */
7946 if (AOP_TYPE (right) == AOP_CRY)
7948 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7949 aopPut (AOP (result), "c", 0);
7955 aopPut (AOP (result), "a", 0);
7959 /* if they are the same size : or less */
7960 if (AOP_SIZE (result) <= AOP_SIZE (right))
7963 /* if they are in the same place */
7964 if (sameRegs (AOP (right), AOP (result)))
7967 /* if they in different places then copy */
7968 size = AOP_SIZE (result);
7972 aopPut (AOP (result),
7973 aopGet (AOP (right), offset, FALSE, FALSE),
7981 /* if the result is of type pointer */
7986 sym_link *type = operandType (right);
7987 sym_link *etype = getSpec (type);
7989 /* pointer to generic pointer */
7990 if (IS_GENPTR (ctype))
7995 p_type = DCL_TYPE (type);
7998 /* we have to go by the storage class */
7999 p_type = PTR_TYPE (SPEC_OCLS (etype));
8002 /* the first two bytes are known */
8003 size = GPTRSIZE - 1;
8007 aopPut (AOP (result),
8008 aopGet (AOP (right), offset, FALSE, FALSE),
8012 /* the last byte depending on type */
8030 /* this should never happen */
8031 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8032 "got unknown pointer type");
8035 aopPut (AOP (result), l, GPTRSIZE - 1);
8039 /* just copy the pointers */
8040 size = AOP_SIZE (result);
8044 aopPut (AOP (result),
8045 aopGet (AOP (right), offset, FALSE, FALSE),
8052 /* so we now know that the size of destination is greater
8053 than the size of the source */
8054 /* we move to result for the size of source */
8055 size = AOP_SIZE (right);
8059 aopPut (AOP (result),
8060 aopGet (AOP (right), offset, FALSE, FALSE),
8065 /* now depending on the sign of the source && destination */
8066 size = AOP_SIZE (result) - AOP_SIZE (right);
8067 /* if unsigned or not an integral type */
8068 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8071 aopPut (AOP (result), zero, offset++);
8075 /* we need to extend the sign :{ */
8076 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8079 emitcode ("rlc", "a");
8080 emitcode ("subb", "a,acc");
8082 aopPut (AOP (result), "a", offset++);
8085 /* we are done hurray !!!! */
8088 freeAsmop (right, NULL, ic, TRUE);
8089 freeAsmop (result, NULL, ic, TRUE);
8093 /*-----------------------------------------------------------------*/
8094 /* genDjnz - generate decrement & jump if not zero instrucion */
8095 /*-----------------------------------------------------------------*/
8097 genDjnz (iCode * ic, iCode * ifx)
8103 /* if the if condition has a false label
8104 then we cannot save */
8108 /* if the minus is not of the form
8110 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8111 !IS_OP_LITERAL (IC_RIGHT (ic)))
8114 if (operandLitValue (IC_RIGHT (ic)) != 1)
8117 /* if the size of this greater than one then no
8119 if (getSize (operandType (IC_RESULT (ic))) > 1)
8122 /* otherwise we can save BIG */
8123 lbl = newiTempLabel (NULL);
8124 lbl1 = newiTempLabel (NULL);
8126 aopOp (IC_RESULT (ic), ic, FALSE);
8128 if (AOP_NEEDSACC(IC_RESULT(ic)))
8130 /* If the result is accessed indirectly via
8131 * the accumulator, we must explicitly write
8132 * it back after the decrement.
8134 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8136 if (strcmp(rByte, "a"))
8138 /* Something is hopelessly wrong */
8139 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8140 __FILE__, __LINE__);
8141 /* We can just give up; the generated code will be inefficient,
8144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8147 emitcode ("dec", "%s", rByte);
8148 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8149 emitcode ("jnz", "%05d$", lbl->key + 100);
8151 else if (IS_AOP_PREG (IC_RESULT (ic)))
8153 emitcode ("dec", "%s",
8154 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8155 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8156 emitcode ("jnz", "%05d$", lbl->key + 100);
8160 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8163 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8164 emitcode ("", "%05d$:", lbl->key + 100);
8165 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8166 emitcode ("", "%05d$:", lbl1->key + 100);
8168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8173 /*-----------------------------------------------------------------*/
8174 /* genReceive - generate code for a receive iCode */
8175 /*-----------------------------------------------------------------*/
8177 genReceive (iCode * ic)
8179 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8180 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8181 IS_TRUE_SYMOP (IC_RESULT (ic))))
8184 int size = getSize (operandType (IC_RESULT (ic)));
8185 int offset = fReturnSizeMCS51 - size;
8188 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8189 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8192 aopOp (IC_RESULT (ic), ic, FALSE);
8193 size = AOP_SIZE (IC_RESULT (ic));
8197 emitcode ("pop", "acc");
8198 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8205 aopOp (IC_RESULT (ic), ic, FALSE);
8207 assignResultValue (IC_RESULT (ic));
8210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8213 /*-----------------------------------------------------------------*/
8214 /* gen51Code - generate code for 8051 based controllers */
8215 /*-----------------------------------------------------------------*/
8217 gen51Code (iCode * lic)
8222 lineHead = lineCurr = NULL;
8224 /* print the allocation information */
8226 printAllocInfo (currFunc, codeOutFile);
8227 /* if debug information required */
8228 /* if (options.debug && currFunc) { */
8231 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8233 if (IS_STATIC (currFunc->etype))
8234 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8236 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8239 /* stack pointer name */
8240 if (options.useXstack)
8246 for (ic = lic; ic; ic = ic->next)
8249 if (cln != ic->lineno)
8254 emitcode ("", "C$%s$%d$%d$%d ==.",
8255 FileBaseName (ic->filename), ic->lineno,
8256 ic->level, ic->block);
8259 emitcode (";", "%s %d", ic->filename, ic->lineno);
8262 /* if the result is marked as
8263 spilt and rematerializable or code for
8264 this has already been generated then
8266 if (resultRemat (ic) || ic->generated)
8269 /* depending on the operation */
8289 /* IPOP happens only when trying to restore a
8290 spilt live range, if there is an ifx statement
8291 following this pop then the if statement might
8292 be using some of the registers being popped which
8293 would destory the contents of the register so
8294 we need to check for this condition and handle it */
8296 ic->next->op == IFX &&
8297 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8298 genIfx (ic->next, ic);
8316 genEndFunction (ic);
8336 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8353 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8357 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8364 /* note these two are xlated by algebraic equivalence
8365 during parsing SDCC.y */
8366 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8367 "got '>=' or '<=' shouldn't have come here");
8371 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8383 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8387 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8391 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8418 case GET_VALUE_AT_ADDRESS:
8419 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8423 if (POINTER_SET (ic))
8424 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8450 addSet (&_G.sendSet, ic);
8459 /* now we are ready to call the
8460 peep hole optimizer */
8461 if (!options.nopeep)
8462 peepHole (&lineHead);
8464 /* now do the actual printing */
8465 printLine (lineHead, codeOutFile);