1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saverbank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[MAX_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1451 /* find the registers in use at this time
1452 and push them away to safety */
1453 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1457 if (options.useXstack)
1459 if (bitVectBitValue (rsave, R0_IDX))
1460 emitcode ("mov", "b,r0");
1461 emitcode ("mov", "r0,%s", spname);
1462 for (i = 0; i < mcs51_nRegs; i++)
1464 if (bitVectBitValue (rsave, i))
1467 emitcode ("mov", "a,b");
1469 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1470 emitcode ("movx", "@r0,a");
1471 emitcode ("inc", "r0");
1474 emitcode ("mov", "%s,r0", spname);
1475 if (bitVectBitValue (rsave, R0_IDX))
1476 emitcode ("mov", "r0,b");
1479 for (i = 0; i < mcs51_nRegs; i++)
1481 if (bitVectBitValue (rsave, i))
1482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1485 detype = getSpec (operandType (IC_LEFT (ic)));
1487 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1488 IS_ISR (currFunc->etype) &&
1491 saverbank (SPEC_BANK (detype), ic, TRUE);
1494 /*-----------------------------------------------------------------*/
1495 /* unsaveRegisters - pop the pushed registers */
1496 /*-----------------------------------------------------------------*/
1498 unsaveRegisters (iCode * ic)
1502 /* find the registers in use at this time
1503 and push them away to safety */
1504 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1507 if (options.useXstack)
1509 emitcode ("mov", "r0,%s", spname);
1510 for (i = mcs51_nRegs; i >= 0; i--)
1512 if (bitVectBitValue (rsave, i))
1514 emitcode ("dec", "r0");
1515 emitcode ("movx", "a,@r0");
1517 emitcode ("mov", "b,a");
1519 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1523 emitcode ("mov", "%s,r0", spname);
1524 if (bitVectBitValue (rsave, R0_IDX))
1525 emitcode ("mov", "r0,b");
1528 for (i = mcs51_nRegs; i >= 0; i--)
1530 if (bitVectBitValue (rsave, i))
1531 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1537 /*-----------------------------------------------------------------*/
1539 /*-----------------------------------------------------------------*/
1541 pushSide (operand * oper, int size)
1546 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1547 if (AOP_TYPE (oper) != AOP_REG &&
1548 AOP_TYPE (oper) != AOP_DIR &&
1551 emitcode ("mov", "a,%s", l);
1552 emitcode ("push", "acc");
1555 emitcode ("push", "%s", l);
1559 /*-----------------------------------------------------------------*/
1560 /* assignResultValue - */
1561 /*-----------------------------------------------------------------*/
1563 assignResultValue (operand * oper)
1566 int size = AOP_SIZE (oper);
1569 aopPut (AOP (oper), fReturn[offset], offset);
1575 /*-----------------------------------------------------------------*/
1576 /* genXpush - pushes onto the external stack */
1577 /*-----------------------------------------------------------------*/
1579 genXpush (iCode * ic)
1581 asmop *aop = newAsmop (0);
1583 int size, offset = 0;
1585 aopOp (IC_LEFT (ic), ic, FALSE);
1586 r = getFreePtr (ic, &aop, FALSE);
1589 emitcode ("mov", "%s,_spx", r->name);
1591 size = AOP_SIZE (IC_LEFT (ic));
1595 char *l = aopGet (AOP (IC_LEFT (ic)),
1596 offset++, FALSE, FALSE);
1598 emitcode ("movx", "@%s,a", r->name);
1599 emitcode ("inc", "%s", r->name);
1604 emitcode ("mov", "_spx,%s", r->name);
1606 freeAsmop (NULL, aop, ic, TRUE);
1607 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1610 /*-----------------------------------------------------------------*/
1611 /* genIpush - genrate code for pushing this gets a little complex */
1612 /*-----------------------------------------------------------------*/
1614 genIpush (iCode * ic)
1616 int size, offset = 0;
1620 /* if this is not a parm push : ie. it is spill push
1621 and spill push is always done on the local stack */
1625 /* and the item is spilt then do nothing */
1626 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1629 aopOp (IC_LEFT (ic), ic, FALSE);
1630 size = AOP_SIZE (IC_LEFT (ic));
1631 /* push it on the stack */
1634 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1640 emitcode ("push", "%s", l);
1645 /* this is a paramter push: in this case we call
1646 the routine to find the call and save those
1647 registers that need to be saved */
1650 /* if use external stack then call the external
1651 stack pushing routine */
1652 if (options.useXstack)
1658 /* then do the push */
1659 aopOp (IC_LEFT (ic), ic, FALSE);
1662 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1663 size = AOP_SIZE (IC_LEFT (ic));
1667 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1668 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1669 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1672 emitcode ("mov", "a,%s", l);
1673 emitcode ("push", "acc");
1676 emitcode ("push", "%s", l);
1679 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1682 /*-----------------------------------------------------------------*/
1683 /* genIpop - recover the registers: can happen only for spilling */
1684 /*-----------------------------------------------------------------*/
1686 genIpop (iCode * ic)
1691 /* if the temp was not pushed then */
1692 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1695 aopOp (IC_LEFT (ic), ic, FALSE);
1696 size = AOP_SIZE (IC_LEFT (ic));
1697 offset = (size - 1);
1699 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1702 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1705 /*-----------------------------------------------------------------*/
1706 /* unsaverbank - restores the resgister bank from stack */
1707 /*-----------------------------------------------------------------*/
1709 unsaverbank (int bank, iCode * ic, bool popPsw)
1717 if (options.useXstack)
1720 r = getFreePtr (ic, &aop, FALSE);
1723 emitcode ("mov", "%s,_spx", r->name);
1724 emitcode ("movx", "a,@%s", r->name);
1725 emitcode ("mov", "psw,a");
1726 emitcode ("dec", "%s", r->name);
1730 emitcode ("pop", "psw");
1733 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1735 if (options.useXstack)
1737 emitcode ("movx", "a,@%s", r->name);
1738 emitcode ("mov", "(%s+%d),a",
1739 regs8051[i].base, 8 * bank + regs8051[i].offset);
1740 emitcode ("dec", "%s", r->name);
1744 emitcode ("pop", "(%s+%d)",
1745 regs8051[i].base, 8 * bank + regs8051[i].offset);
1748 if (options.useXstack)
1751 emitcode ("mov", "_spx,%s", r->name);
1752 freeAsmop (NULL, aop, ic, TRUE);
1757 /*-----------------------------------------------------------------*/
1758 /* saverbank - saves an entire register bank on the stack */
1759 /*-----------------------------------------------------------------*/
1761 saverbank (int bank, iCode * ic, bool pushPsw)
1767 if (options.useXstack)
1771 r = getFreePtr (ic, &aop, FALSE);
1772 emitcode ("mov", "%s,_spx", r->name);
1776 for (i = 0; i < mcs51_nRegs; i++)
1778 if (options.useXstack)
1780 emitcode ("inc", "%s", r->name);
1781 emitcode ("mov", "a,(%s+%d)",
1782 regs8051[i].base, 8 * bank + regs8051[i].offset);
1783 emitcode ("movx", "@%s,a", r->name);
1786 emitcode ("push", "(%s+%d)",
1787 regs8051[i].base, 8 * bank + regs8051[i].offset);
1792 if (options.useXstack)
1794 emitcode ("mov", "a,psw");
1795 emitcode ("movx", "@%s,a", r->name);
1796 emitcode ("inc", "%s", r->name);
1797 emitcode ("mov", "_spx,%s", r->name);
1798 freeAsmop (NULL, aop, ic, TRUE);
1802 emitcode ("push", "psw");
1804 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1810 /*-----------------------------------------------------------------*/
1811 /* genCall - generates a call statement */
1812 /*-----------------------------------------------------------------*/
1814 genCall (iCode * ic)
1818 /* if caller saves & we have not saved then */
1822 /* if we are calling a function that is not using
1823 the same register bank then we need to save the
1824 destination registers on the stack */
1825 detype = getSpec (operandType (IC_LEFT (ic)));
1827 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1828 IS_ISR (currFunc->etype) &&
1831 saverbank (SPEC_BANK (detype), ic, TRUE);
1833 /* if send set is not empty the assign */
1838 for (sic = setFirstItem (_G.sendSet); sic;
1839 sic = setNextItem (_G.sendSet))
1841 int size, offset = 0;
1842 aopOp (IC_LEFT (sic), sic, FALSE);
1843 size = AOP_SIZE (IC_LEFT (sic));
1846 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1848 if (strcmp (l, fReturn[offset]))
1849 emitcode ("mov", "%s,%s",
1854 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1859 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1860 OP_SYMBOL (IC_LEFT (ic))->rname :
1861 OP_SYMBOL (IC_LEFT (ic))->name));
1863 /* if we need assign a result value */
1864 if ((IS_ITEMP (IC_RESULT (ic)) &&
1865 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1866 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1867 IS_TRUE_SYMOP (IC_RESULT (ic)))
1871 aopOp (IC_RESULT (ic), ic, FALSE);
1874 assignResultValue (IC_RESULT (ic));
1876 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1879 /* adjust the stack for parameters if
1884 if (ic->parmBytes > 3)
1886 emitcode ("mov", "a,%s", spname);
1887 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1888 emitcode ("mov", "%s,a", spname);
1891 for (i = 0; i < ic->parmBytes; i++)
1892 emitcode ("dec", "%s", spname);
1896 /* if register bank was saved then pop them */
1898 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1900 /* if we hade saved some registers then unsave them */
1901 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1902 unsaveRegisters (ic);
1907 /*-----------------------------------------------------------------*/
1908 /* genPcall - generates a call by pointer statement */
1909 /*-----------------------------------------------------------------*/
1911 genPcall (iCode * ic)
1914 symbol *rlbl = newiTempLabel (NULL);
1917 /* if caller saves & we have not saved then */
1921 /* if we are calling a function that is not using
1922 the same register bank then we need to save the
1923 destination registers on the stack */
1924 detype = getSpec (operandType (IC_LEFT (ic)));
1926 IS_ISR (currFunc->etype) &&
1927 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1928 saverbank (SPEC_BANK (detype), ic, TRUE);
1931 /* push the return address on to the stack */
1932 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1933 emitcode ("push", "acc");
1934 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1935 emitcode ("push", "acc");
1937 /* now push the calling address */
1938 aopOp (IC_LEFT (ic), ic, FALSE);
1940 pushSide (IC_LEFT (ic), FPTRSIZE);
1942 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1944 /* if send set is not empty the assign */
1949 for (sic = setFirstItem (_G.sendSet); sic;
1950 sic = setNextItem (_G.sendSet))
1952 int size, offset = 0;
1953 aopOp (IC_LEFT (sic), sic, FALSE);
1954 size = AOP_SIZE (IC_LEFT (sic));
1957 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1959 if (strcmp (l, fReturn[offset]))
1960 emitcode ("mov", "%s,%s",
1965 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1970 emitcode ("ret", "");
1971 emitcode ("", "%05d$:", (rlbl->key + 100));
1974 /* if we need assign a result value */
1975 if ((IS_ITEMP (IC_RESULT (ic)) &&
1976 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1977 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1978 IS_TRUE_SYMOP (IC_RESULT (ic)))
1982 aopOp (IC_RESULT (ic), ic, FALSE);
1985 assignResultValue (IC_RESULT (ic));
1987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1990 /* adjust the stack for parameters if
1995 if (ic->parmBytes > 3)
1997 emitcode ("mov", "a,%s", spname);
1998 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1999 emitcode ("mov", "%s,a", spname);
2002 for (i = 0; i < ic->parmBytes; i++)
2003 emitcode ("dec", "%s", spname);
2007 /* if register bank was saved then unsave them */
2009 (SPEC_BANK (currFunc->etype) !=
2010 SPEC_BANK (detype)))
2011 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2013 /* if we hade saved some registers then
2016 unsaveRegisters (ic);
2020 /*-----------------------------------------------------------------*/
2021 /* resultRemat - result is rematerializable */
2022 /*-----------------------------------------------------------------*/
2024 resultRemat (iCode * ic)
2026 if (SKIP_IC (ic) || ic->op == IFX)
2029 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2031 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2032 if (sym->remat && !POINTER_SET (ic))
2039 #if defined(__BORLANDC__) || defined(_MSC_VER)
2040 #define STRCASECMP stricmp
2042 #define STRCASECMP strcasecmp
2045 /*-----------------------------------------------------------------*/
2046 /* inExcludeList - return 1 if the string is in exclude Reg list */
2047 /*-----------------------------------------------------------------*/
2049 inExcludeList (char *s)
2053 if (options.excludeRegs[i] &&
2054 STRCASECMP (options.excludeRegs[i], "none") == 0)
2057 for (i = 0; options.excludeRegs[i]; i++)
2059 if (options.excludeRegs[i] &&
2060 STRCASECMP (s, options.excludeRegs[i]) == 0)
2066 /*-----------------------------------------------------------------*/
2067 /* genFunction - generated code for function entry */
2068 /*-----------------------------------------------------------------*/
2070 genFunction (iCode * ic)
2076 /* create the function header */
2077 emitcode (";", "-----------------------------------------");
2078 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2079 emitcode (";", "-----------------------------------------");
2081 emitcode ("", "%s:", sym->rname);
2082 fetype = getSpec (operandType (IC_LEFT (ic)));
2084 /* if critical function then turn interrupts off */
2085 if (SPEC_CRTCL (fetype))
2086 emitcode ("clr", "ea");
2088 /* here we need to generate the equates for the
2089 register bank if required */
2090 if (SPEC_BANK (fetype) != rbank)
2094 rbank = SPEC_BANK (fetype);
2095 for (i = 0; i < mcs51_nRegs; i++)
2097 if (strcmp (regs8051[i].base, "0") == 0)
2098 emitcode ("", "%s = 0x%02x",
2100 8 * rbank + regs8051[i].offset);
2102 emitcode ("", "%s = %s + 0x%02x",
2105 8 * rbank + regs8051[i].offset);
2109 /* if this is an interrupt service routine then
2110 save acc, b, dpl, dph */
2111 if (IS_ISR (sym->etype))
2114 if (!inExcludeList ("acc"))
2115 emitcode ("push", "acc");
2116 if (!inExcludeList ("b"))
2117 emitcode ("push", "b");
2118 if (!inExcludeList ("dpl"))
2119 emitcode ("push", "dpl");
2120 if (!inExcludeList ("dph"))
2121 emitcode ("push", "dph");
2122 /* if this isr has no bank i.e. is going to
2123 run with bank 0 , then we need to save more
2125 if (!SPEC_BANK (sym->etype))
2128 /* if this function does not call any other
2129 function then we can be economical and
2130 save only those registers that are used */
2135 /* if any registers used */
2138 /* save the registers used */
2139 for (i = 0; i < sym->regsUsed->size; i++)
2141 if (bitVectBitValue (sym->regsUsed, i) ||
2142 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2143 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2150 /* this function has a function call cannot
2151 determines register usage so we will have the
2153 saverbank (0, ic, FALSE);
2159 /* if callee-save to be used for this function
2160 then save the registers being used in this function */
2161 if (sym->calleeSave)
2165 /* if any registers used */
2168 /* save the registers used */
2169 for (i = 0; i < sym->regsUsed->size; i++)
2171 if (bitVectBitValue (sym->regsUsed, i) ||
2172 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2174 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2182 /* set the register bank to the desired value */
2183 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2185 emitcode ("push", "psw");
2186 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2189 if (IS_RENT (sym->etype) || options.stackAuto)
2192 if (options.useXstack)
2194 emitcode ("mov", "r0,%s", spname);
2195 emitcode ("mov", "a,_bp");
2196 emitcode ("movx", "@r0,a");
2197 emitcode ("inc", "%s", spname);
2201 /* set up the stack */
2202 emitcode ("push", "_bp"); /* save the callers stack */
2204 emitcode ("mov", "_bp,%s", spname);
2207 /* adjust the stack for the function */
2213 werror (W_STACK_OVERFLOW, sym->name);
2215 if (i > 3 && sym->recvSize < 4)
2218 emitcode ("mov", "a,sp");
2219 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2220 emitcode ("mov", "sp,a");
2225 emitcode ("inc", "sp");
2231 emitcode ("mov", "a,_spx");
2232 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2233 emitcode ("mov", "_spx,a");
2238 /*-----------------------------------------------------------------*/
2239 /* genEndFunction - generates epilogue for functions */
2240 /*-----------------------------------------------------------------*/
2242 genEndFunction (iCode * ic)
2244 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2246 if (IS_RENT (sym->etype) || options.stackAuto)
2248 emitcode ("mov", "%s,_bp", spname);
2251 /* if use external stack but some variables were
2252 added to the local stack then decrement the
2254 if (options.useXstack && sym->stack)
2256 emitcode ("mov", "a,sp");
2257 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2258 emitcode ("mov", "sp,a");
2262 if ((IS_RENT (sym->etype) || options.stackAuto))
2264 if (options.useXstack)
2266 emitcode ("mov", "r0,%s", spname);
2267 emitcode ("movx", "a,@r0");
2268 emitcode ("mov", "_bp,a");
2269 emitcode ("dec", "%s", spname);
2273 emitcode ("pop", "_bp");
2277 /* restore the register bank */
2278 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2279 emitcode ("pop", "psw");
2281 if (IS_ISR (sym->etype))
2284 /* now we need to restore the registers */
2285 /* if this isr has no bank i.e. is going to
2286 run with bank 0 , then we need to save more
2288 if (!SPEC_BANK (sym->etype))
2291 /* if this function does not call any other
2292 function then we can be economical and
2293 save only those registers that are used */
2298 /* if any registers used */
2301 /* save the registers used */
2302 for (i = sym->regsUsed->size; i >= 0; i--)
2304 if (bitVectBitValue (sym->regsUsed, i) ||
2305 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2306 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2313 /* this function has a function call cannot
2314 determines register usage so we will have the
2316 unsaverbank (0, ic, FALSE);
2320 if (!inExcludeList ("dph"))
2321 emitcode ("pop", "dph");
2322 if (!inExcludeList ("dpl"))
2323 emitcode ("pop", "dpl");
2324 if (!inExcludeList ("b"))
2325 emitcode ("pop", "b");
2326 if (!inExcludeList ("acc"))
2327 emitcode ("pop", "acc");
2329 if (SPEC_CRTCL (sym->etype))
2330 emitcode ("setb", "ea");
2332 /* if debug then send end of function */
2333 /* if (options.debug && currFunc) { */
2337 emitcode ("", "C$%s$%d$%d$%d ==.",
2338 FileBaseName (ic->filename), currFunc->lastLine,
2339 ic->level, ic->block);
2340 if (IS_STATIC (currFunc->etype))
2341 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2343 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2347 emitcode ("reti", "");
2351 if (SPEC_CRTCL (sym->etype))
2352 emitcode ("setb", "ea");
2354 if (sym->calleeSave)
2358 /* if any registers used */
2361 /* save the registers used */
2362 for (i = sym->regsUsed->size; i >= 0; i--)
2364 if (bitVectBitValue (sym->regsUsed, i) ||
2365 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2366 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2372 /* if debug then send end of function */
2376 emitcode ("", "C$%s$%d$%d$%d ==.",
2377 FileBaseName (ic->filename), currFunc->lastLine,
2378 ic->level, ic->block);
2379 if (IS_STATIC (currFunc->etype))
2380 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2382 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2386 emitcode ("ret", "");
2391 /*-----------------------------------------------------------------*/
2392 /* genRet - generate code for return statement */
2393 /*-----------------------------------------------------------------*/
2397 int size, offset = 0, pushed = 0;
2399 /* if we have no return value then
2400 just generate the "ret" */
2404 /* we have something to return then
2405 move the return value into place */
2406 aopOp (IC_LEFT (ic), ic, FALSE);
2407 size = AOP_SIZE (IC_LEFT (ic));
2412 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2415 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2417 emitcode ("push", "%s", l);
2422 l = aopGet (AOP (IC_LEFT (ic)), offset,
2424 if (strcmp (fReturn[offset], l))
2425 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2434 if (strcmp (fReturn[pushed], "a"))
2435 emitcode ("pop", fReturn[pushed]);
2437 emitcode ("pop", "acc");
2440 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2443 /* generate a jump to the return label
2444 if the next is not the return statement */
2445 if (!(ic->next && ic->next->op == LABEL &&
2446 IC_LABEL (ic->next) == returnLabel))
2448 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2452 /*-----------------------------------------------------------------*/
2453 /* genLabel - generates a label */
2454 /*-----------------------------------------------------------------*/
2456 genLabel (iCode * ic)
2458 /* special case never generate */
2459 if (IC_LABEL (ic) == entryLabel)
2462 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2465 /*-----------------------------------------------------------------*/
2466 /* genGoto - generates a ljmp */
2467 /*-----------------------------------------------------------------*/
2469 genGoto (iCode * ic)
2471 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2474 /*-----------------------------------------------------------------*/
2475 /* findLabelBackwards: walks back through the iCode chain looking */
2476 /* for the given label. Returns number of iCode instructions */
2477 /* between that label and given ic. */
2478 /* Returns zero if label not found. */
2479 /*-----------------------------------------------------------------*/
2481 findLabelBackwards (iCode * ic, int key)
2490 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2492 /* printf("findLabelBackwards = %d\n", count); */
2500 /*-----------------------------------------------------------------*/
2501 /* genPlusIncr :- does addition with increment if possible */
2502 /*-----------------------------------------------------------------*/
2504 genPlusIncr (iCode * ic)
2506 unsigned int icount;
2507 unsigned int size = getDataSize (IC_RESULT (ic));
2509 /* will try to generate an increment */
2510 /* if the right side is not a literal
2512 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2515 /* if the literal value of the right hand side
2516 is greater than 4 then it is not worth it */
2517 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2520 /* if increment 16 bits in register */
2521 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2529 /* If the next instruction is a goto and the goto target
2530 * is < 10 instructions previous to this, we can generate
2531 * jumps straight to that target.
2533 if (ic->next && ic->next->op == GOTO
2534 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2535 && labelRange <= 10)
2537 emitcode (";", "tail increment optimized");
2538 tlbl = IC_LABEL (ic->next);
2543 tlbl = newiTempLabel (NULL);
2546 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2547 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2548 IS_AOP_PREG (IC_RESULT (ic)))
2549 emitcode ("cjne", "%s,#0x00,%05d$"
2550 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2554 emitcode ("clr", "a");
2555 emitcode ("cjne", "a,%s,%05d$"
2556 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2560 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2563 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2564 IS_AOP_PREG (IC_RESULT (ic)))
2565 emitcode ("cjne", "%s,#0x00,%05d$"
2566 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2569 emitcode ("cjne", "a,%s,%05d$"
2570 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2573 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2577 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2578 IS_AOP_PREG (IC_RESULT (ic)))
2579 emitcode ("cjne", "%s,#0x00,%05d$"
2580 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2584 emitcode ("cjne", "a,%s,%05d$"
2585 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2588 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2593 emitcode ("", "%05d$:", tlbl->key + 100);
2598 /* if the sizes are greater than 1 then we cannot */
2599 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2600 AOP_SIZE (IC_LEFT (ic)) > 1)
2603 /* we can if the aops of the left & result match or
2604 if they are in registers and the registers are the
2606 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2611 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2612 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2613 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2619 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2628 /*-----------------------------------------------------------------*/
2629 /* outBitAcc - output a bit in acc */
2630 /*-----------------------------------------------------------------*/
2632 outBitAcc (operand * result)
2634 symbol *tlbl = newiTempLabel (NULL);
2635 /* if the result is a bit */
2636 if (AOP_TYPE (result) == AOP_CRY)
2638 aopPut (AOP (result), "a", 0);
2642 emitcode ("jz", "%05d$", tlbl->key + 100);
2643 emitcode ("mov", "a,%s", one);
2644 emitcode ("", "%05d$:", tlbl->key + 100);
2649 /*-----------------------------------------------------------------*/
2650 /* genPlusBits - generates code for addition of two bits */
2651 /*-----------------------------------------------------------------*/
2653 genPlusBits (iCode * ic)
2655 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2657 symbol *lbl = newiTempLabel (NULL);
2658 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2659 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2660 emitcode ("cpl", "c");
2661 emitcode ("", "%05d$:", (lbl->key + 100));
2662 outBitC (IC_RESULT (ic));
2666 emitcode ("clr", "a");
2667 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2668 emitcode ("rlc", "a");
2669 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2670 emitcode ("addc", "a,#0x00");
2671 outAcc (IC_RESULT (ic));
2676 /* This is the original version of this code.
2678 * This is being kept around for reference,
2679 * because I am not entirely sure I got it right...
2682 adjustArithmeticResult (iCode * ic)
2684 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2685 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2686 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2687 aopPut (AOP (IC_RESULT (ic)),
2688 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2691 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2692 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2693 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2694 aopPut (AOP (IC_RESULT (ic)),
2695 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2698 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2699 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2700 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2701 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2702 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2705 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2706 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2710 /* This is the pure and virtuous version of this code.
2711 * I'm pretty certain it's right, but not enough to toss the old
2715 adjustArithmeticResult (iCode * ic)
2717 if (opIsGptr (IC_RESULT (ic)) &&
2718 opIsGptr (IC_LEFT (ic)) &&
2719 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2721 aopPut (AOP (IC_RESULT (ic)),
2722 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2726 if (opIsGptr (IC_RESULT (ic)) &&
2727 opIsGptr (IC_RIGHT (ic)) &&
2728 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2730 aopPut (AOP (IC_RESULT (ic)),
2731 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2735 if (opIsGptr (IC_RESULT (ic)) &&
2736 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2737 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2738 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2739 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2742 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2743 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2748 /*-----------------------------------------------------------------*/
2749 /* genPlus - generates code for addition */
2750 /*-----------------------------------------------------------------*/
2752 genPlus (iCode * ic)
2754 int size, offset = 0;
2756 /* special cases :- */
2758 aopOp (IC_LEFT (ic), ic, FALSE);
2759 aopOp (IC_RIGHT (ic), ic, FALSE);
2760 aopOp (IC_RESULT (ic), ic, TRUE);
2762 /* if literal, literal on the right or
2763 if left requires ACC or right is already
2765 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2766 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2767 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2769 operand *t = IC_RIGHT (ic);
2770 IC_RIGHT (ic) = IC_LEFT (ic);
2774 /* if both left & right are in bit
2776 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2777 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2783 /* if left in bit space & right literal */
2784 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2785 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2787 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2788 /* if result in bit space */
2789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2791 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2792 emitcode ("cpl", "c");
2793 outBitC (IC_RESULT (ic));
2797 size = getDataSize (IC_RESULT (ic));
2800 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2801 emitcode ("addc", "a,#00");
2802 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2808 /* if I can do an increment instead
2809 of add then GOOD for ME */
2810 if (genPlusIncr (ic) == TRUE)
2813 size = getDataSize (IC_RESULT (ic));
2817 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2819 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2821 emitcode ("add", "a,%s",
2822 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2824 emitcode ("addc", "a,%s",
2825 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2829 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2831 emitcode ("add", "a,%s",
2832 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2834 emitcode ("addc", "a,%s",
2835 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2837 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2840 adjustArithmeticResult (ic);
2843 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2844 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2848 /*-----------------------------------------------------------------*/
2849 /* genMinusDec :- does subtraction with deccrement if possible */
2850 /*-----------------------------------------------------------------*/
2852 genMinusDec (iCode * ic)
2854 unsigned int icount;
2855 unsigned int size = getDataSize (IC_RESULT (ic));
2857 /* will try to generate an increment */
2858 /* if the right side is not a literal
2860 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2863 /* if the literal value of the right hand side
2864 is greater than 4 then it is not worth it */
2865 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2868 /* if decrement 16 bits in register */
2869 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2877 /* If the next instruction is a goto and the goto target
2878 * is <= 10 instructions previous to this, we can generate
2879 * jumps straight to that target.
2881 if (ic->next && ic->next->op == GOTO
2882 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2883 && labelRange <= 10)
2885 emitcode (";", "tail decrement optimized");
2886 tlbl = IC_LABEL (ic->next);
2891 tlbl = newiTempLabel (NULL);
2895 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2896 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2897 IS_AOP_PREG (IC_RESULT (ic)))
2898 emitcode ("cjne", "%s,#0xff,%05d$"
2899 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2903 emitcode ("mov", "a,#0xff");
2904 emitcode ("cjne", "a,%s,%05d$"
2905 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2908 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2911 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2912 IS_AOP_PREG (IC_RESULT (ic)))
2913 emitcode ("cjne", "%s,#0xff,%05d$"
2914 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2918 emitcode ("cjne", "a,%s,%05d$"
2919 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2922 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2926 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2927 IS_AOP_PREG (IC_RESULT (ic)))
2928 emitcode ("cjne", "%s,#0xff,%05d$"
2929 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2933 emitcode ("cjne", "a,%s,%05d$"
2934 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2937 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2941 emitcode ("", "%05d$:", tlbl->key + 100);
2946 /* if the sizes are greater than 1 then we cannot */
2947 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2948 AOP_SIZE (IC_LEFT (ic)) > 1)
2951 /* we can if the aops of the left & result match or
2952 if they are in registers and the registers are the
2954 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2958 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
2966 /*-----------------------------------------------------------------*/
2967 /* addSign - complete with sign */
2968 /*-----------------------------------------------------------------*/
2970 addSign (operand * result, int offset, int sign)
2972 int size = (getDataSize (result) - offset);
2977 emitcode ("rlc", "a");
2978 emitcode ("subb", "a,acc");
2980 aopPut (AOP (result), "a", offset++);
2984 aopPut (AOP (result), zero, offset++);
2988 /*-----------------------------------------------------------------*/
2989 /* genMinusBits - generates code for subtraction of two bits */
2990 /*-----------------------------------------------------------------*/
2992 genMinusBits (iCode * ic)
2994 symbol *lbl = newiTempLabel (NULL);
2995 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2997 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2998 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2999 emitcode ("cpl", "c");
3000 emitcode ("", "%05d$:", (lbl->key + 100));
3001 outBitC (IC_RESULT (ic));
3005 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3006 emitcode ("subb", "a,acc");
3007 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3008 emitcode ("inc", "a");
3009 emitcode ("", "%05d$:", (lbl->key + 100));
3010 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3011 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3015 /*-----------------------------------------------------------------*/
3016 /* genMinus - generates code for subtraction */
3017 /*-----------------------------------------------------------------*/
3019 genMinus (iCode * ic)
3021 int size, offset = 0;
3022 unsigned long lit = 0L;
3024 aopOp (IC_LEFT (ic), ic, FALSE);
3025 aopOp (IC_RIGHT (ic), ic, FALSE);
3026 aopOp (IC_RESULT (ic), ic, TRUE);
3028 /* special cases :- */
3029 /* if both left & right are in bit space */
3030 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3031 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3037 /* if I can do an decrement instead
3038 of subtract then GOOD for ME */
3039 if (genMinusDec (ic) == TRUE)
3042 size = getDataSize (IC_RESULT (ic));
3044 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3050 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3054 /* if literal, add a,#-lit, else normal subb */
3057 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3058 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3059 emitcode ("subb", "a,%s",
3060 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3063 /* first add without previous c */
3065 emitcode ("add", "a,#0x%02x",
3066 (unsigned int) (lit & 0x0FFL));
3068 emitcode ("addc", "a,#0x%02x",
3069 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3071 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3074 adjustArithmeticResult (ic);
3077 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3078 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3079 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3083 /*-----------------------------------------------------------------*/
3084 /* genMultbits :- multiplication of bits */
3085 /*-----------------------------------------------------------------*/
3087 genMultbits (operand * left,
3091 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3092 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3097 /*-----------------------------------------------------------------*/
3098 /* genMultOneByte : 8*8=8/16 bit multiplication */
3099 /*-----------------------------------------------------------------*/
3101 genMultOneByte (operand * left,
3105 sym_link *opetype = operandType (result);
3107 int size=AOP_SIZE(result);
3109 //emitcode (";",__FUNCTION__);
3110 if (size<1 || size>2) {
3111 // this should never happen
3112 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3113 AOP_SIZE(result), __FUNCTION__, lineno);
3117 /* (if two literals: the value is computed before) */
3118 /* if one literal, literal on the right */
3119 if (AOP_TYPE (left) == AOP_LIT)
3124 //emitcode (";", "swapped left and right");
3127 if (SPEC_USIGN(opetype)
3128 // ignore the sign of left and right, what else can we do?
3129 || (SPEC_USIGN(operandType(left)) &&
3130 SPEC_USIGN(operandType(right)))) {
3131 // just an unsigned 8*8=8/16 multiply
3132 //emitcode (";","unsigned");
3133 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3134 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3135 emitcode ("mul", "ab");
3136 aopPut (AOP (result), "a", 0);
3138 aopPut (AOP (result), "b", 1);
3143 // we have to do a signed multiply
3145 //emitcode (";", "signed");
3146 emitcode ("clr", "F0"); // reset sign flag
3147 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3148 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3150 lbl=newiTempLabel(NULL);
3151 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3152 // left side is negative, 8-bit two's complement, this fails for -128
3153 emitcode ("setb", "F0"); // set sign flag
3154 emitcode ("cpl", "a");
3155 emitcode ("inc", "a");
3157 emitcode ("", "%05d$:", lbl->key+100);
3158 emitcode ("xch", "a,b");
3161 if (AOP_TYPE(right)==AOP_LIT) {
3162 /* AND literal negative */
3163 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3164 // two's complement for literal<0
3165 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3166 emitcode ("cpl", "a");
3167 emitcode ("inc", "a");
3170 lbl=newiTempLabel(NULL);
3171 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3172 // right side is negative, 8-bit two's complement
3173 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3174 emitcode ("cpl", "a");
3175 emitcode ("inc", "a");
3176 emitcode ("", "%05d$:", lbl->key+100);
3178 emitcode ("mul", "ab");
3180 lbl=newiTempLabel(NULL);
3181 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3182 // only ONE op was negative, we have to do a 8/16-bit two's complement
3183 emitcode ("cpl", "a"); // lsb
3185 emitcode ("inc", "a");
3187 emitcode ("add", "a,#1");
3188 emitcode ("xch", "a,b");
3189 emitcode ("cpl", "a"); // msb
3190 emitcode ("addc", "a,#0");
3191 emitcode ("xch", "a,b");
3194 emitcode ("", "%05d$:", lbl->key+100);
3195 aopPut (AOP (result), "a", 0);
3197 aopPut (AOP (result), "b", 1);
3201 /*-----------------------------------------------------------------*/
3202 /* genMult - generates code for multiplication */
3203 /*-----------------------------------------------------------------*/
3205 genMult (iCode * ic)
3207 operand *left = IC_LEFT (ic);
3208 operand *right = IC_RIGHT (ic);
3209 operand *result = IC_RESULT (ic);
3211 /* assign the amsops */
3212 aopOp (left, ic, FALSE);
3213 aopOp (right, ic, FALSE);
3214 aopOp (result, ic, TRUE);
3216 /* special cases first */
3218 if (AOP_TYPE (left) == AOP_CRY &&
3219 AOP_TYPE (right) == AOP_CRY)
3221 genMultbits (left, right, result);
3225 /* if both are of size == 1 */
3226 if (AOP_SIZE (left) == 1 &&
3227 AOP_SIZE (right) == 1)
3229 genMultOneByte (left, right, result);
3233 /* should have been converted to function call */
3237 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3238 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3239 freeAsmop (result, NULL, ic, TRUE);
3242 /*-----------------------------------------------------------------*/
3243 /* genDivbits :- division of bits */
3244 /*-----------------------------------------------------------------*/
3246 genDivbits (operand * left,
3253 /* the result must be bit */
3254 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3255 l = aopGet (AOP (left), 0, FALSE, FALSE);
3259 emitcode ("div", "ab");
3260 emitcode ("rrc", "a");
3261 aopPut (AOP (result), "c", 0);
3264 /*-----------------------------------------------------------------*/
3265 /* genDivOneByte : 8 bit division */
3266 /*-----------------------------------------------------------------*/
3268 genDivOneByte (operand * left,
3272 sym_link *opetype = operandType (result);
3277 size = AOP_SIZE (result) - 1;
3279 /* signed or unsigned */
3280 if (SPEC_USIGN (opetype))
3282 /* unsigned is easy */
3283 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3284 l = aopGet (AOP (left), 0, FALSE, FALSE);
3286 emitcode ("div", "ab");
3287 aopPut (AOP (result), "a", 0);
3289 aopPut (AOP (result), zero, offset++);
3293 /* signed is a little bit more difficult */
3295 /* save the signs of the operands */
3296 l = aopGet (AOP (left), 0, FALSE, FALSE);
3298 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3299 emitcode ("push", "acc"); /* save it on the stack */
3301 /* now sign adjust for both left & right */
3302 l = aopGet (AOP (right), 0, FALSE, FALSE);
3304 lbl = newiTempLabel (NULL);
3305 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3306 emitcode ("cpl", "a");
3307 emitcode ("inc", "a");
3308 emitcode ("", "%05d$:", (lbl->key + 100));
3309 emitcode ("mov", "b,a");
3311 /* sign adjust left side */
3312 l = aopGet (AOP (left), 0, FALSE, FALSE);
3315 lbl = newiTempLabel (NULL);
3316 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3317 emitcode ("cpl", "a");
3318 emitcode ("inc", "a");
3319 emitcode ("", "%05d$:", (lbl->key + 100));
3321 /* now the division */
3322 emitcode ("div", "ab");
3323 /* we are interested in the lower order
3325 emitcode ("mov", "b,a");
3326 lbl = newiTempLabel (NULL);
3327 emitcode ("pop", "acc");
3328 /* if there was an over flow we don't
3329 adjust the sign of the result */
3330 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3331 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3333 emitcode ("clr", "a");
3334 emitcode ("subb", "a,b");
3335 emitcode ("mov", "b,a");
3336 emitcode ("", "%05d$:", (lbl->key + 100));
3338 /* now we are done */
3339 aopPut (AOP (result), "b", 0);
3342 emitcode ("mov", "c,b.7");
3343 emitcode ("subb", "a,acc");
3346 aopPut (AOP (result), "a", offset++);
3350 /*-----------------------------------------------------------------*/
3351 /* genDiv - generates code for division */
3352 /*-----------------------------------------------------------------*/
3356 operand *left = IC_LEFT (ic);
3357 operand *right = IC_RIGHT (ic);
3358 operand *result = IC_RESULT (ic);
3360 /* assign the amsops */
3361 aopOp (left, ic, FALSE);
3362 aopOp (right, ic, FALSE);
3363 aopOp (result, ic, TRUE);
3365 /* special cases first */
3367 if (AOP_TYPE (left) == AOP_CRY &&
3368 AOP_TYPE (right) == AOP_CRY)
3370 genDivbits (left, right, result);
3374 /* if both are of size == 1 */
3375 if (AOP_SIZE (left) == 1 &&
3376 AOP_SIZE (right) == 1)
3378 genDivOneByte (left, right, result);
3382 /* should have been converted to function call */
3385 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3387 freeAsmop (result, NULL, ic, TRUE);
3390 /*-----------------------------------------------------------------*/
3391 /* genModbits :- modulus of bits */
3392 /*-----------------------------------------------------------------*/
3394 genModbits (operand * left,
3401 /* the result must be bit */
3402 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3403 l = aopGet (AOP (left), 0, FALSE, FALSE);
3407 emitcode ("div", "ab");
3408 emitcode ("mov", "a,b");
3409 emitcode ("rrc", "a");
3410 aopPut (AOP (result), "c", 0);
3413 /*-----------------------------------------------------------------*/
3414 /* genModOneByte : 8 bit modulus */
3415 /*-----------------------------------------------------------------*/
3417 genModOneByte (operand * left,
3421 sym_link *opetype = operandType (result);
3425 /* signed or unsigned */
3426 if (SPEC_USIGN (opetype))
3428 /* unsigned is easy */
3429 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3430 l = aopGet (AOP (left), 0, FALSE, FALSE);
3432 emitcode ("div", "ab");
3433 aopPut (AOP (result), "b", 0);
3437 /* signed is a little bit more difficult */
3439 /* save the signs of the operands */
3440 l = aopGet (AOP (left), 0, FALSE, FALSE);
3443 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3444 emitcode ("push", "acc"); /* save it on the stack */
3446 /* now sign adjust for both left & right */
3447 l = aopGet (AOP (right), 0, FALSE, FALSE);
3450 lbl = newiTempLabel (NULL);
3451 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3452 emitcode ("cpl", "a");
3453 emitcode ("inc", "a");
3454 emitcode ("", "%05d$:", (lbl->key + 100));
3455 emitcode ("mov", "b,a");
3457 /* sign adjust left side */
3458 l = aopGet (AOP (left), 0, FALSE, FALSE);
3461 lbl = newiTempLabel (NULL);
3462 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3463 emitcode ("cpl", "a");
3464 emitcode ("inc", "a");
3465 emitcode ("", "%05d$:", (lbl->key + 100));
3467 /* now the multiplication */
3468 emitcode ("div", "ab");
3469 /* we are interested in the lower order
3471 lbl = newiTempLabel (NULL);
3472 emitcode ("pop", "acc");
3473 /* if there was an over flow we don't
3474 adjust the sign of the result */
3475 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3476 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3478 emitcode ("clr", "a");
3479 emitcode ("subb", "a,b");
3480 emitcode ("mov", "b,a");
3481 emitcode ("", "%05d$:", (lbl->key + 100));
3483 /* now we are done */
3484 aopPut (AOP (result), "b", 0);
3488 /*-----------------------------------------------------------------*/
3489 /* genMod - generates code for division */
3490 /*-----------------------------------------------------------------*/
3494 operand *left = IC_LEFT (ic);
3495 operand *right = IC_RIGHT (ic);
3496 operand *result = IC_RESULT (ic);
3498 /* assign the amsops */
3499 aopOp (left, ic, FALSE);
3500 aopOp (right, ic, FALSE);
3501 aopOp (result, ic, TRUE);
3503 /* special cases first */
3505 if (AOP_TYPE (left) == AOP_CRY &&
3506 AOP_TYPE (right) == AOP_CRY)
3508 genModbits (left, right, result);
3512 /* if both are of size == 1 */
3513 if (AOP_SIZE (left) == 1 &&
3514 AOP_SIZE (right) == 1)
3516 genModOneByte (left, right, result);
3520 /* should have been converted to function call */
3524 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3525 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3526 freeAsmop (result, NULL, ic, TRUE);
3529 /*-----------------------------------------------------------------*/
3530 /* genIfxJump :- will create a jump depending on the ifx */
3531 /*-----------------------------------------------------------------*/
3533 genIfxJump (iCode * ic, char *jval)
3536 symbol *tlbl = newiTempLabel (NULL);
3539 /* if true label then we jump if condition
3543 jlbl = IC_TRUE (ic);
3544 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3545 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3549 /* false label is present */
3550 jlbl = IC_FALSE (ic);
3551 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3552 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3554 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3555 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3557 emitcode (inst, "%05d$", tlbl->key + 100);
3558 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3559 emitcode ("", "%05d$:", tlbl->key + 100);
3561 /* mark the icode as generated */
3565 /*-----------------------------------------------------------------*/
3566 /* genCmp :- greater or less than comparison */
3567 /*-----------------------------------------------------------------*/
3569 genCmp (operand * left, operand * right,
3570 operand * result, iCode * ifx, int sign, iCode *ic)
3572 int size, offset = 0;
3573 unsigned long lit = 0L;
3575 /* if left & right are bit variables */
3576 if (AOP_TYPE (left) == AOP_CRY &&
3577 AOP_TYPE (right) == AOP_CRY)
3579 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3580 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3584 /* subtract right from left if at the
3585 end the carry flag is set then we know that
3586 left is greater than right */
3587 size = max (AOP_SIZE (left), AOP_SIZE (right));
3589 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3590 if ((size == 1) && !sign &&
3591 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3593 symbol *lbl = newiTempLabel (NULL);
3594 emitcode ("cjne", "%s,%s,%05d$",
3595 aopGet (AOP (left), offset, FALSE, FALSE),
3596 aopGet (AOP (right), offset, FALSE, FALSE),
3598 emitcode ("", "%05d$:", lbl->key + 100);
3602 if (AOP_TYPE (right) == AOP_LIT)
3604 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3605 /* optimize if(x < 0) or if(x >= 0) */
3614 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3615 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3617 genIfxJump (ifx, "acc.7");
3621 emitcode ("rlc", "a");
3629 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3630 if (sign && size == 0)
3632 emitcode ("xrl", "a,#0x80");
3633 if (AOP_TYPE (right) == AOP_LIT)
3635 unsigned long lit = (unsigned long)
3636 floatFromVal (AOP (right)->aopu.aop_lit);
3637 emitcode ("subb", "a,#0x%02x",
3638 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3642 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3643 emitcode ("xrl", "b,#0x80");
3644 emitcode ("subb", "a,b");
3648 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3654 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3655 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3656 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3662 /* if the result is used in the next
3663 ifx conditional branch then generate
3664 code a little differently */
3666 genIfxJump (ifx, "c");
3669 /* leave the result in acc */
3673 /*-----------------------------------------------------------------*/
3674 /* genCmpGt :- greater than comparison */
3675 /*-----------------------------------------------------------------*/
3677 genCmpGt (iCode * ic, iCode * ifx)
3679 operand *left, *right, *result;
3680 sym_link *letype, *retype;
3683 left = IC_LEFT (ic);
3684 right = IC_RIGHT (ic);
3685 result = IC_RESULT (ic);
3687 letype = getSpec (operandType (left));
3688 retype = getSpec (operandType (right));
3689 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3690 /* assign the amsops */
3691 aopOp (left, ic, FALSE);
3692 aopOp (right, ic, FALSE);
3693 aopOp (result, ic, TRUE);
3695 genCmp (right, left, result, ifx, sign,ic);
3697 freeAsmop (result, NULL, ic, TRUE);
3700 /*-----------------------------------------------------------------*/
3701 /* genCmpLt - less than comparisons */
3702 /*-----------------------------------------------------------------*/
3704 genCmpLt (iCode * ic, iCode * ifx)
3706 operand *left, *right, *result;
3707 sym_link *letype, *retype;
3710 left = IC_LEFT (ic);
3711 right = IC_RIGHT (ic);
3712 result = IC_RESULT (ic);
3714 letype = getSpec (operandType (left));
3715 retype = getSpec (operandType (right));
3716 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3718 /* assign the amsops */
3719 aopOp (left, ic, FALSE);
3720 aopOp (right, ic, FALSE);
3721 aopOp (result, ic, TRUE);
3723 genCmp (left, right, result, ifx, sign,ic);
3725 freeAsmop (result, NULL, ic, TRUE);
3728 /*-----------------------------------------------------------------*/
3729 /* gencjneshort - compare and jump if not equal */
3730 /*-----------------------------------------------------------------*/
3732 gencjneshort (operand * left, operand * right, symbol * lbl)
3734 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3736 unsigned long lit = 0L;
3738 /* if the left side is a literal or
3739 if the right is in a pointer register and left
3741 if ((AOP_TYPE (left) == AOP_LIT) ||
3742 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3748 if (AOP_TYPE (right) == AOP_LIT)
3749 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3751 /* if the right side is a literal then anything goes */
3752 if (AOP_TYPE (right) == AOP_LIT &&
3753 AOP_TYPE (left) != AOP_DIR)
3757 emitcode ("cjne", "%s,%s,%05d$",
3758 aopGet (AOP (left), offset, FALSE, FALSE),
3759 aopGet (AOP (right), offset, FALSE, FALSE),
3765 /* if the right side is in a register or in direct space or
3766 if the left is a pointer register & right is not */
3767 else if (AOP_TYPE (right) == AOP_REG ||
3768 AOP_TYPE (right) == AOP_DIR ||
3769 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3770 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3774 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3775 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3776 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3777 emitcode ("jnz", "%05d$", lbl->key + 100);
3779 emitcode ("cjne", "a,%s,%05d$",
3780 aopGet (AOP (right), offset, FALSE, TRUE),
3787 /* right is a pointer reg need both a & b */
3790 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3791 if (strcmp (l, "b"))
3792 emitcode ("mov", "b,%s", l);
3793 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3794 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3800 /*-----------------------------------------------------------------*/
3801 /* gencjne - compare and jump if not equal */
3802 /*-----------------------------------------------------------------*/
3804 gencjne (operand * left, operand * right, symbol * lbl)
3806 symbol *tlbl = newiTempLabel (NULL);
3808 gencjneshort (left, right, lbl);
3810 emitcode ("mov", "a,%s", one);
3811 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3812 emitcode ("", "%05d$:", lbl->key + 100);
3813 emitcode ("clr", "a");
3814 emitcode ("", "%05d$:", tlbl->key + 100);
3817 /*-----------------------------------------------------------------*/
3818 /* genCmpEq - generates code for equal to */
3819 /*-----------------------------------------------------------------*/
3821 genCmpEq (iCode * ic, iCode * ifx)
3823 operand *left, *right, *result;
3825 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3826 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3827 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3829 /* if literal, literal on the right or
3830 if the right is in a pointer register and left
3832 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3833 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3835 operand *t = IC_RIGHT (ic);
3836 IC_RIGHT (ic) = IC_LEFT (ic);
3840 if (ifx && !AOP_SIZE (result))
3843 /* if they are both bit variables */
3844 if (AOP_TYPE (left) == AOP_CRY &&
3845 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3847 if (AOP_TYPE (right) == AOP_LIT)
3849 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3852 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3853 emitcode ("cpl", "c");
3857 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3861 emitcode ("clr", "c");
3863 /* AOP_TYPE(right) == AOP_CRY */
3867 symbol *lbl = newiTempLabel (NULL);
3868 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3869 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3870 emitcode ("cpl", "c");
3871 emitcode ("", "%05d$:", (lbl->key + 100));
3873 /* if true label then we jump if condition
3875 tlbl = newiTempLabel (NULL);
3878 emitcode ("jnc", "%05d$", tlbl->key + 100);
3879 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3883 emitcode ("jc", "%05d$", tlbl->key + 100);
3884 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3886 emitcode ("", "%05d$:", tlbl->key + 100);
3890 tlbl = newiTempLabel (NULL);
3891 gencjneshort (left, right, tlbl);
3894 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3895 emitcode ("", "%05d$:", tlbl->key + 100);
3899 symbol *lbl = newiTempLabel (NULL);
3900 emitcode ("sjmp", "%05d$", lbl->key + 100);
3901 emitcode ("", "%05d$:", tlbl->key + 100);
3902 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3903 emitcode ("", "%05d$:", lbl->key + 100);
3906 /* mark the icode as generated */
3911 /* if they are both bit variables */
3912 if (AOP_TYPE (left) == AOP_CRY &&
3913 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3915 if (AOP_TYPE (right) == AOP_LIT)
3917 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3921 emitcode ("cpl", "c");
3925 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3929 emitcode ("clr", "c");
3931 /* AOP_TYPE(right) == AOP_CRY */
3935 symbol *lbl = newiTempLabel (NULL);
3936 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3937 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3938 emitcode ("cpl", "c");
3939 emitcode ("", "%05d$:", (lbl->key + 100));
3942 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3949 genIfxJump (ifx, "c");
3952 /* if the result is used in an arithmetic operation
3953 then put the result in place */
3958 gencjne (left, right, newiTempLabel (NULL));
3959 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3961 aopPut (AOP (result), "a", 0);
3966 genIfxJump (ifx, "a");
3969 /* if the result is used in an arithmetic operation
3970 then put the result in place */
3971 if (AOP_TYPE (result) != AOP_CRY)
3973 /* leave the result in acc */
3977 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3978 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3979 freeAsmop (result, NULL, ic, TRUE);
3982 /*-----------------------------------------------------------------*/
3983 /* ifxForOp - returns the icode containing the ifx for operand */
3984 /*-----------------------------------------------------------------*/
3986 ifxForOp (operand * op, iCode * ic)
3988 /* if true symbol then needs to be assigned */
3989 if (IS_TRUE_SYMOP (op))
3992 /* if this has register type condition and
3993 the next instruction is ifx with the same operand
3994 and live to of the operand is upto the ifx only then */
3996 ic->next->op == IFX &&
3997 IC_COND (ic->next)->key == op->key &&
3998 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4004 /*-----------------------------------------------------------------*/
4005 /* hasInc - operand is incremented before any other use */
4006 /*-----------------------------------------------------------------*/
4008 hasInc (operand *op, iCode *ic)
4010 sym_link *type = operandType(op);
4011 sym_link *retype = getSpec (type);
4012 iCode *lic = ic->next;
4015 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4016 isize = getSize(type->next);
4018 /* if operand of the form op = op + <sizeof *op> */
4019 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4020 isOperandEqual(IC_RESULT(lic),op) &&
4021 isOperandLiteral(IC_RIGHT(lic)) &&
4022 operandLitValue(IC_RIGHT(lic)) == isize) {
4025 /* if the operand used or deffed */
4026 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4034 /*-----------------------------------------------------------------*/
4035 /* genAndOp - for && operation */
4036 /*-----------------------------------------------------------------*/
4038 genAndOp (iCode * ic)
4040 operand *left, *right, *result;
4043 /* note here that && operations that are in an
4044 if statement are taken away by backPatchLabels
4045 only those used in arthmetic operations remain */
4046 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4047 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4048 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4050 /* if both are bit variables */
4051 if (AOP_TYPE (left) == AOP_CRY &&
4052 AOP_TYPE (right) == AOP_CRY)
4054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4055 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4060 tlbl = newiTempLabel (NULL);
4062 emitcode ("jz", "%05d$", tlbl->key + 100);
4064 emitcode ("", "%05d$:", tlbl->key + 100);
4068 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4070 freeAsmop (result, NULL, ic, TRUE);
4074 /*-----------------------------------------------------------------*/
4075 /* genOrOp - for || operation */
4076 /*-----------------------------------------------------------------*/
4078 genOrOp (iCode * ic)
4080 operand *left, *right, *result;
4083 /* note here that || operations that are in an
4084 if statement are taken away by backPatchLabels
4085 only those used in arthmetic operations remain */
4086 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4087 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4088 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4090 /* if both are bit variables */
4091 if (AOP_TYPE (left) == AOP_CRY &&
4092 AOP_TYPE (right) == AOP_CRY)
4094 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4095 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4100 tlbl = newiTempLabel (NULL);
4102 emitcode ("jnz", "%05d$", tlbl->key + 100);
4104 emitcode ("", "%05d$:", tlbl->key + 100);
4108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4110 freeAsmop (result, NULL, ic, TRUE);
4113 /*-----------------------------------------------------------------*/
4114 /* isLiteralBit - test if lit == 2^n */
4115 /*-----------------------------------------------------------------*/
4117 isLiteralBit (unsigned long lit)
4119 unsigned long pw[32] =
4120 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4121 0x100L, 0x200L, 0x400L, 0x800L,
4122 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4123 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4124 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4125 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4126 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4129 for (idx = 0; idx < 32; idx++)
4135 /*-----------------------------------------------------------------*/
4136 /* continueIfTrue - */
4137 /*-----------------------------------------------------------------*/
4139 continueIfTrue (iCode * ic)
4142 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4146 /*-----------------------------------------------------------------*/
4148 /*-----------------------------------------------------------------*/
4150 jumpIfTrue (iCode * ic)
4153 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4157 /*-----------------------------------------------------------------*/
4158 /* jmpTrueOrFalse - */
4159 /*-----------------------------------------------------------------*/
4161 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4163 // ugly but optimized by peephole
4166 symbol *nlbl = newiTempLabel (NULL);
4167 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4168 emitcode ("", "%05d$:", tlbl->key + 100);
4169 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4170 emitcode ("", "%05d$:", nlbl->key + 100);
4174 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4175 emitcode ("", "%05d$:", tlbl->key + 100);
4180 /*-----------------------------------------------------------------*/
4181 /* genAnd - code for and */
4182 /*-----------------------------------------------------------------*/
4184 genAnd (iCode * ic, iCode * ifx)
4186 operand *left, *right, *result;
4187 int size, offset = 0;
4188 unsigned long lit = 0L;
4192 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4193 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4194 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4197 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4199 AOP_TYPE (left), AOP_TYPE (right));
4200 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4202 AOP_SIZE (left), AOP_SIZE (right));
4205 /* if left is a literal & right is not then exchange them */
4206 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4207 AOP_NEEDSACC (left))
4209 operand *tmp = right;
4214 /* if result = right then exchange them */
4215 if (sameRegs (AOP (result), AOP (right)))
4217 operand *tmp = right;
4222 /* if right is bit then exchange them */
4223 if (AOP_TYPE (right) == AOP_CRY &&
4224 AOP_TYPE (left) != AOP_CRY)
4226 operand *tmp = right;
4230 if (AOP_TYPE (right) == AOP_LIT)
4231 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4233 size = AOP_SIZE (result);
4236 // result = bit & yy;
4237 if (AOP_TYPE (left) == AOP_CRY)
4239 // c = bit & literal;
4240 if (AOP_TYPE (right) == AOP_LIT)
4244 if (size && sameRegs (AOP (result), AOP (left)))
4247 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4252 if (size && (AOP_TYPE (result) == AOP_CRY))
4254 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4257 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4262 emitcode ("clr", "c");
4267 if (AOP_TYPE (right) == AOP_CRY)
4270 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4271 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4276 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4278 emitcode ("rrc", "a");
4279 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4287 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4288 genIfxJump (ifx, "c");
4292 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4293 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4294 if ((AOP_TYPE (right) == AOP_LIT) &&
4295 (AOP_TYPE (result) == AOP_CRY) &&
4296 (AOP_TYPE (left) != AOP_CRY))
4298 int posbit = isLiteralBit (lit);
4303 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4306 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4312 sprintf (buffer, "acc.%d", posbit & 0x07);
4313 genIfxJump (ifx, buffer);
4320 symbol *tlbl = newiTempLabel (NULL);
4321 int sizel = AOP_SIZE (left);
4323 emitcode ("setb", "c");
4326 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4328 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4330 if ((posbit = isLiteralBit (bytelit)) != 0)
4331 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4334 if (bytelit != 0x0FFL)
4335 emitcode ("anl", "a,%s",
4336 aopGet (AOP (right), offset, FALSE, TRUE));
4337 emitcode ("jnz", "%05d$", tlbl->key + 100);
4342 // bit = left & literal
4345 emitcode ("clr", "c");
4346 emitcode ("", "%05d$:", tlbl->key + 100);
4348 // if(left & literal)
4352 jmpTrueOrFalse (ifx, tlbl);
4360 /* if left is same as result */
4361 if (sameRegs (AOP (result), AOP (left)))
4363 for (; size--; offset++)
4365 if (AOP_TYPE (right) == AOP_LIT)
4367 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4369 else if (bytelit == 0)
4370 aopPut (AOP (result), zero, offset);
4371 else if (IS_AOP_PREG (result))
4373 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4374 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4375 aopPut (AOP (result), "a", offset);
4378 emitcode ("anl", "%s,%s",
4379 aopGet (AOP (left), offset, FALSE, TRUE),
4380 aopGet (AOP (right), offset, FALSE, FALSE));
4384 if (AOP_TYPE (left) == AOP_ACC)
4385 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4389 if (IS_AOP_PREG (result))
4391 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4392 aopPut (AOP (result), "a", offset);
4396 emitcode ("anl", "%s,a",
4397 aopGet (AOP (left), offset, FALSE, TRUE));
4404 // left & result in different registers
4405 if (AOP_TYPE (result) == AOP_CRY)
4408 // if(size), result in bit
4409 // if(!size && ifx), conditional oper: if(left & right)
4410 symbol *tlbl = newiTempLabel (NULL);
4411 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4413 emitcode ("setb", "c");
4416 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4417 emitcode ("anl", "a,%s",
4418 aopGet (AOP (left), offset, FALSE, FALSE));
4419 emitcode ("jnz", "%05d$", tlbl->key + 100);
4425 emitcode ("", "%05d$:", tlbl->key + 100);
4429 jmpTrueOrFalse (ifx, tlbl);
4433 for (; (size--); offset++)
4436 // result = left & right
4437 if (AOP_TYPE (right) == AOP_LIT)
4439 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4441 aopPut (AOP (result),
4442 aopGet (AOP (left), offset, FALSE, FALSE),
4446 else if (bytelit == 0)
4448 aopPut (AOP (result), zero, offset);
4452 // faster than result <- left, anl result,right
4453 // and better if result is SFR
4454 if (AOP_TYPE (left) == AOP_ACC)
4455 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4458 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4459 emitcode ("anl", "a,%s",
4460 aopGet (AOP (left), offset, FALSE, FALSE));
4462 aopPut (AOP (result), "a", offset);
4468 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4469 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470 freeAsmop (result, NULL, ic, TRUE);
4473 /*-----------------------------------------------------------------*/
4474 /* genOr - code for or */
4475 /*-----------------------------------------------------------------*/
4477 genOr (iCode * ic, iCode * ifx)
4479 operand *left, *right, *result;
4480 int size, offset = 0;
4481 unsigned long lit = 0L;
4483 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4484 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4485 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4488 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4490 AOP_TYPE (left), AOP_TYPE (right));
4491 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4493 AOP_SIZE (left), AOP_SIZE (right));
4496 /* if left is a literal & right is not then exchange them */
4497 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4498 AOP_NEEDSACC (left))
4500 operand *tmp = right;
4505 /* if result = right then exchange them */
4506 if (sameRegs (AOP (result), AOP (right)))
4508 operand *tmp = right;
4513 /* if right is bit then exchange them */
4514 if (AOP_TYPE (right) == AOP_CRY &&
4515 AOP_TYPE (left) != AOP_CRY)
4517 operand *tmp = right;
4521 if (AOP_TYPE (right) == AOP_LIT)
4522 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4524 size = AOP_SIZE (result);
4528 if (AOP_TYPE (left) == AOP_CRY)
4530 if (AOP_TYPE (right) == AOP_LIT)
4532 // c = bit & literal;
4535 // lit != 0 => result = 1
4536 if (AOP_TYPE (result) == AOP_CRY)
4539 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4541 continueIfTrue (ifx);
4544 emitcode ("setb", "c");
4548 // lit == 0 => result = left
4549 if (size && sameRegs (AOP (result), AOP (left)))
4551 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4556 if (AOP_TYPE (right) == AOP_CRY)
4559 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4560 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4565 symbol *tlbl = newiTempLabel (NULL);
4566 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4567 emitcode ("setb", "c");
4568 emitcode ("jb", "%s,%05d$",
4569 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4571 emitcode ("jnz", "%05d$", tlbl->key + 100);
4572 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4574 jmpTrueOrFalse (ifx, tlbl);
4580 emitcode ("", "%05d$:", tlbl->key + 100);
4589 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4590 genIfxJump (ifx, "c");
4594 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4595 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4596 if ((AOP_TYPE (right) == AOP_LIT) &&
4597 (AOP_TYPE (result) == AOP_CRY) &&
4598 (AOP_TYPE (left) != AOP_CRY))
4604 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4606 continueIfTrue (ifx);
4611 // lit = 0, result = boolean(left)
4613 emitcode ("setb", "c");
4617 symbol *tlbl = newiTempLabel (NULL);
4618 emitcode ("jnz", "%05d$", tlbl->key + 100);
4620 emitcode ("", "%05d$:", tlbl->key + 100);
4624 genIfxJump (ifx, "a");
4632 /* if left is same as result */
4633 if (sameRegs (AOP (result), AOP (left)))
4635 for (; size--; offset++)
4637 if (AOP_TYPE (right) == AOP_LIT)
4639 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4641 else if (IS_AOP_PREG (left))
4643 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4644 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4645 aopPut (AOP (result), "a", offset);
4648 emitcode ("orl", "%s,%s",
4649 aopGet (AOP (left), offset, FALSE, TRUE),
4650 aopGet (AOP (right), offset, FALSE, FALSE));
4654 if (AOP_TYPE (left) == AOP_ACC)
4655 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4658 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4659 if (IS_AOP_PREG (left))
4661 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4662 aopPut (AOP (result), "a", offset);
4665 emitcode ("orl", "%s,a",
4666 aopGet (AOP (left), offset, FALSE, TRUE));
4673 // left & result in different registers
4674 if (AOP_TYPE (result) == AOP_CRY)
4677 // if(size), result in bit
4678 // if(!size && ifx), conditional oper: if(left | right)
4679 symbol *tlbl = newiTempLabel (NULL);
4680 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4682 emitcode ("setb", "c");
4685 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4686 emitcode ("orl", "a,%s",
4687 aopGet (AOP (left), offset, FALSE, FALSE));
4688 emitcode ("jnz", "%05d$", tlbl->key + 100);
4694 emitcode ("", "%05d$:", tlbl->key + 100);
4698 jmpTrueOrFalse (ifx, tlbl);
4701 for (; (size--); offset++)
4704 // result = left & right
4705 if (AOP_TYPE (right) == AOP_LIT)
4707 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4709 aopPut (AOP (result),
4710 aopGet (AOP (left), offset, FALSE, FALSE),
4715 // faster than result <- left, anl result,right
4716 // and better if result is SFR
4717 if (AOP_TYPE (left) == AOP_ACC)
4718 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4721 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4722 emitcode ("orl", "a,%s",
4723 aopGet (AOP (left), offset, FALSE, FALSE));
4725 aopPut (AOP (result), "a", offset);
4730 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4732 freeAsmop (result, NULL, ic, TRUE);
4735 /*-----------------------------------------------------------------*/
4736 /* genXor - code for xclusive or */
4737 /*-----------------------------------------------------------------*/
4739 genXor (iCode * ic, iCode * ifx)
4741 operand *left, *right, *result;
4742 int size, offset = 0;
4743 unsigned long lit = 0L;
4745 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4746 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4747 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4750 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4752 AOP_TYPE (left), AOP_TYPE (right));
4753 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4755 AOP_SIZE (left), AOP_SIZE (right));
4758 /* if left is a literal & right is not ||
4759 if left needs acc & right does not */
4760 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4761 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4763 operand *tmp = right;
4768 /* if result = right then exchange them */
4769 if (sameRegs (AOP (result), AOP (right)))
4771 operand *tmp = right;
4776 /* if right is bit then exchange them */
4777 if (AOP_TYPE (right) == AOP_CRY &&
4778 AOP_TYPE (left) != AOP_CRY)
4780 operand *tmp = right;
4784 if (AOP_TYPE (right) == AOP_LIT)
4785 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4787 size = AOP_SIZE (result);
4791 if (AOP_TYPE (left) == AOP_CRY)
4793 if (AOP_TYPE (right) == AOP_LIT)
4795 // c = bit & literal;
4798 // lit>>1 != 0 => result = 1
4799 if (AOP_TYPE (result) == AOP_CRY)
4802 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4804 continueIfTrue (ifx);
4807 emitcode ("setb", "c");
4814 // lit == 0, result = left
4815 if (size && sameRegs (AOP (result), AOP (left)))
4817 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4821 // lit == 1, result = not(left)
4822 if (size && sameRegs (AOP (result), AOP (left)))
4824 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4829 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4830 emitcode ("cpl", "c");
4839 symbol *tlbl = newiTempLabel (NULL);
4840 if (AOP_TYPE (right) == AOP_CRY)
4843 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4847 int sizer = AOP_SIZE (right);
4849 // if val>>1 != 0, result = 1
4850 emitcode ("setb", "c");
4853 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4855 // test the msb of the lsb
4856 emitcode ("anl", "a,#0xfe");
4857 emitcode ("jnz", "%05d$", tlbl->key + 100);
4861 emitcode ("rrc", "a");
4863 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4864 emitcode ("cpl", "c");
4865 emitcode ("", "%05d$:", (tlbl->key + 100));
4872 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4873 genIfxJump (ifx, "c");
4877 if (sameRegs (AOP (result), AOP (left)))
4879 /* if left is same as result */
4880 for (; size--; offset++)
4882 if (AOP_TYPE (right) == AOP_LIT)
4884 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4886 else if (IS_AOP_PREG (left))
4888 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4889 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4890 aopPut (AOP (result), "a", offset);
4893 emitcode ("xrl", "%s,%s",
4894 aopGet (AOP (left), offset, FALSE, TRUE),
4895 aopGet (AOP (right), offset, FALSE, FALSE));
4899 if (AOP_TYPE (left) == AOP_ACC)
4900 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4903 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4904 if (IS_AOP_PREG (left))
4906 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4907 aopPut (AOP (result), "a", offset);
4910 emitcode ("xrl", "%s,a",
4911 aopGet (AOP (left), offset, FALSE, TRUE));
4918 // left & result in different registers
4919 if (AOP_TYPE (result) == AOP_CRY)
4922 // if(size), result in bit
4923 // if(!size && ifx), conditional oper: if(left ^ right)
4924 symbol *tlbl = newiTempLabel (NULL);
4925 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4927 emitcode ("setb", "c");
4930 if ((AOP_TYPE (right) == AOP_LIT) &&
4931 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4933 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4937 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4938 emitcode ("xrl", "a,%s",
4939 aopGet (AOP (left), offset, FALSE, FALSE));
4941 emitcode ("jnz", "%05d$", tlbl->key + 100);
4947 emitcode ("", "%05d$:", tlbl->key + 100);
4951 jmpTrueOrFalse (ifx, tlbl);
4954 for (; (size--); offset++)
4957 // result = left & right
4958 if (AOP_TYPE (right) == AOP_LIT)
4960 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4962 aopPut (AOP (result),
4963 aopGet (AOP (left), offset, FALSE, FALSE),
4968 // faster than result <- left, anl result,right
4969 // and better if result is SFR
4970 if (AOP_TYPE (left) == AOP_ACC)
4971 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4974 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4975 emitcode ("xrl", "a,%s",
4976 aopGet (AOP (left), offset, FALSE, TRUE));
4978 aopPut (AOP (result), "a", offset);
4983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 freeAsmop (result, NULL, ic, TRUE);
4988 /*-----------------------------------------------------------------*/
4989 /* genInline - write the inline code out */
4990 /*-----------------------------------------------------------------*/
4992 genInline (iCode * ic)
4994 char buffer[MAX_INLINEASM];
4998 _G.inLine += (!options.asmpeep);
4999 strcpy (buffer, IC_INLINE (ic));
5001 /* emit each line as a code */
5026 /* emitcode("",buffer); */
5027 _G.inLine -= (!options.asmpeep);
5030 /*-----------------------------------------------------------------*/
5031 /* genRRC - rotate right with carry */
5032 /*-----------------------------------------------------------------*/
5036 operand *left, *result;
5037 int size, offset = 0;
5040 /* rotate right with carry */
5041 left = IC_LEFT (ic);
5042 result = IC_RESULT (ic);
5043 aopOp (left, ic, FALSE);
5044 aopOp (result, ic, FALSE);
5046 /* move it to the result */
5047 size = AOP_SIZE (result);
5052 l = aopGet (AOP (left), offset, FALSE, FALSE);
5054 emitcode ("rrc", "a");
5055 if (AOP_SIZE (result) > 1)
5056 aopPut (AOP (result), "a", offset--);
5058 /* now we need to put the carry into the
5059 highest order byte of the result */
5060 if (AOP_SIZE (result) > 1)
5062 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5065 emitcode ("mov", "acc.7,c");
5066 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5067 freeAsmop (left, NULL, ic, TRUE);
5068 freeAsmop (result, NULL, ic, TRUE);
5071 /*-----------------------------------------------------------------*/
5072 /* genRLC - generate code for rotate left with carry */
5073 /*-----------------------------------------------------------------*/
5077 operand *left, *result;
5078 int size, offset = 0;
5081 /* rotate right with carry */
5082 left = IC_LEFT (ic);
5083 result = IC_RESULT (ic);
5084 aopOp (left, ic, FALSE);
5085 aopOp (result, ic, FALSE);
5087 /* move it to the result */
5088 size = AOP_SIZE (result);
5092 l = aopGet (AOP (left), offset, FALSE, FALSE);
5094 emitcode ("add", "a,acc");
5095 if (AOP_SIZE (result) > 1)
5096 aopPut (AOP (result), "a", offset++);
5099 l = aopGet (AOP (left), offset, FALSE, FALSE);
5101 emitcode ("rlc", "a");
5102 if (AOP_SIZE (result) > 1)
5103 aopPut (AOP (result), "a", offset++);
5106 /* now we need to put the carry into the
5107 highest order byte of the result */
5108 if (AOP_SIZE (result) > 1)
5110 l = aopGet (AOP (result), 0, FALSE, FALSE);
5113 emitcode ("mov", "acc.0,c");
5114 aopPut (AOP (result), "a", 0);
5115 freeAsmop (left, NULL, ic, TRUE);
5116 freeAsmop (result, NULL, ic, TRUE);
5119 /*-----------------------------------------------------------------*/
5120 /* genGetHbit - generates code get highest order bit */
5121 /*-----------------------------------------------------------------*/
5123 genGetHbit (iCode * ic)
5125 operand *left, *result;
5126 left = IC_LEFT (ic);
5127 result = IC_RESULT (ic);
5128 aopOp (left, ic, FALSE);
5129 aopOp (result, ic, FALSE);
5131 /* get the highest order byte into a */
5132 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5133 if (AOP_TYPE (result) == AOP_CRY)
5135 emitcode ("rlc", "a");
5140 emitcode ("rl", "a");
5141 emitcode ("anl", "a,#0x01");
5146 freeAsmop (left, NULL, ic, TRUE);
5147 freeAsmop (result, NULL, ic, TRUE);
5150 /*-----------------------------------------------------------------*/
5151 /* AccRol - rotate left accumulator by known count */
5152 /*-----------------------------------------------------------------*/
5154 AccRol (int shCount)
5156 shCount &= 0x0007; // shCount : 0..7
5163 emitcode ("rl", "a");
5166 emitcode ("rl", "a");
5167 emitcode ("rl", "a");
5170 emitcode ("swap", "a");
5171 emitcode ("rr", "a");
5174 emitcode ("swap", "a");
5177 emitcode ("swap", "a");
5178 emitcode ("rl", "a");
5181 emitcode ("rr", "a");
5182 emitcode ("rr", "a");
5185 emitcode ("rr", "a");
5190 /*-----------------------------------------------------------------*/
5191 /* AccLsh - left shift accumulator by known count */
5192 /*-----------------------------------------------------------------*/
5194 AccLsh (int shCount)
5199 emitcode ("add", "a,acc");
5200 else if (shCount == 2)
5202 emitcode ("add", "a,acc");
5203 emitcode ("add", "a,acc");
5207 /* rotate left accumulator */
5209 /* and kill the lower order bits */
5210 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5215 /*-----------------------------------------------------------------*/
5216 /* AccRsh - right shift accumulator by known count */
5217 /*-----------------------------------------------------------------*/
5219 AccRsh (int shCount)
5226 emitcode ("rrc", "a");
5230 /* rotate right accumulator */
5231 AccRol (8 - shCount);
5232 /* and kill the higher order bits */
5233 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5238 /*-----------------------------------------------------------------*/
5239 /* AccSRsh - signed right shift accumulator by known count */
5240 /*-----------------------------------------------------------------*/
5242 AccSRsh (int shCount)
5249 emitcode ("mov", "c,acc.7");
5250 emitcode ("rrc", "a");
5252 else if (shCount == 2)
5254 emitcode ("mov", "c,acc.7");
5255 emitcode ("rrc", "a");
5256 emitcode ("mov", "c,acc.7");
5257 emitcode ("rrc", "a");
5261 tlbl = newiTempLabel (NULL);
5262 /* rotate right accumulator */
5263 AccRol (8 - shCount);
5264 /* and kill the higher order bits */
5265 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5266 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5267 emitcode ("orl", "a,#0x%02x",
5268 (unsigned char) ~SRMask[shCount]);
5269 emitcode ("", "%05d$:", tlbl->key + 100);
5274 /*-----------------------------------------------------------------*/
5275 /* shiftR1Left2Result - shift right one byte from left to result */
5276 /*-----------------------------------------------------------------*/
5278 shiftR1Left2Result (operand * left, int offl,
5279 operand * result, int offr,
5280 int shCount, int sign)
5282 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5283 /* shift right accumulator */
5288 aopPut (AOP (result), "a", offr);
5291 /*-----------------------------------------------------------------*/
5292 /* shiftL1Left2Result - shift left one byte from left to result */
5293 /*-----------------------------------------------------------------*/
5295 shiftL1Left2Result (operand * left, int offl,
5296 operand * result, int offr, int shCount)
5299 l = aopGet (AOP (left), offl, FALSE, FALSE);
5301 /* shift left accumulator */
5303 aopPut (AOP (result), "a", offr);
5306 /*-----------------------------------------------------------------*/
5307 /* movLeft2Result - move byte from left to result */
5308 /*-----------------------------------------------------------------*/
5310 movLeft2Result (operand * left, int offl,
5311 operand * result, int offr, int sign)
5314 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5316 l = aopGet (AOP (left), offl, FALSE, FALSE);
5318 if (*l == '@' && (IS_AOP_PREG (result)))
5320 emitcode ("mov", "a,%s", l);
5321 aopPut (AOP (result), "a", offr);
5326 aopPut (AOP (result), l, offr);
5329 /* MSB sign in acc.7 ! */
5330 if (getDataSize (left) == offl + 1)
5332 emitcode ("mov", "a,%s", l);
5333 aopPut (AOP (result), "a", offr);
5340 /*-----------------------------------------------------------------*/
5341 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5342 /*-----------------------------------------------------------------*/
5346 emitcode ("rrc", "a");
5347 emitcode ("xch", "a,%s", x);
5348 emitcode ("rrc", "a");
5349 emitcode ("xch", "a,%s", x);
5352 /*-----------------------------------------------------------------*/
5353 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5354 /*-----------------------------------------------------------------*/
5358 emitcode ("xch", "a,%s", x);
5359 emitcode ("rlc", "a");
5360 emitcode ("xch", "a,%s", x);
5361 emitcode ("rlc", "a");
5364 /*-----------------------------------------------------------------*/
5365 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5366 /*-----------------------------------------------------------------*/
5370 emitcode ("xch", "a,%s", x);
5371 emitcode ("add", "a,acc");
5372 emitcode ("xch", "a,%s", x);
5373 emitcode ("rlc", "a");
5376 /*-----------------------------------------------------------------*/
5377 /* AccAXLsh - left shift a:x by known count (0..7) */
5378 /*-----------------------------------------------------------------*/
5380 AccAXLsh (char *x, int shCount)
5395 case 5: // AAAAABBB:CCCCCDDD
5397 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5399 emitcode ("anl", "a,#0x%02x",
5400 SLMask[shCount]); // BBB00000:CCCCCDDD
5402 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5404 AccRol (shCount); // DDDCCCCC:BBB00000
5406 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5408 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5410 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5412 emitcode ("anl", "a,#0x%02x",
5413 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5415 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5417 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5420 case 6: // AAAAAABB:CCCCCCDD
5421 emitcode ("anl", "a,#0x%02x",
5422 SRMask[shCount]); // 000000BB:CCCCCCDD
5423 emitcode ("mov", "c,acc.0"); // c = B
5424 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5426 AccAXRrl1 (x); // BCCCCCCD:D000000B
5427 AccAXRrl1 (x); // BBCCCCCC:DD000000
5429 emitcode("rrc","a");
5430 emitcode("xch","a,%s", x);
5431 emitcode("rrc","a");
5432 emitcode("mov","c,acc.0"); //<< get correct bit
5433 emitcode("xch","a,%s", x);
5435 emitcode("rrc","a");
5436 emitcode("xch","a,%s", x);
5437 emitcode("rrc","a");
5438 emitcode("xch","a,%s", x);
5441 case 7: // a:x <<= 7
5443 emitcode ("anl", "a,#0x%02x",
5444 SRMask[shCount]); // 0000000B:CCCCCCCD
5446 emitcode ("mov", "c,acc.0"); // c = B
5448 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5450 AccAXRrl1 (x); // BCCCCCCC:D0000000
5458 /*-----------------------------------------------------------------*/
5459 /* AccAXRsh - right shift a:x known count (0..7) */
5460 /*-----------------------------------------------------------------*/
5462 AccAXRsh (char *x, int shCount)
5470 AccAXRrl1 (x); // 0->a:x
5475 AccAXRrl1 (x); // 0->a:x
5478 AccAXRrl1 (x); // 0->a:x
5483 case 5: // AAAAABBB:CCCCCDDD = a:x
5485 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5487 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5489 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5491 emitcode ("anl", "a,#0x%02x",
5492 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5494 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5496 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5498 emitcode ("anl", "a,#0x%02x",
5499 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5501 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5503 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5505 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5508 case 6: // AABBBBBB:CCDDDDDD
5510 emitcode ("mov", "c,acc.7");
5511 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5513 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5515 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5517 emitcode ("anl", "a,#0x%02x",
5518 SRMask[shCount]); // 000000AA:BBBBBBCC
5521 case 7: // ABBBBBBB:CDDDDDDD
5523 emitcode ("mov", "c,acc.7"); // c = A
5525 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5527 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5529 emitcode ("anl", "a,#0x%02x",
5530 SRMask[shCount]); // 0000000A:BBBBBBBC
5538 /*-----------------------------------------------------------------*/
5539 /* AccAXRshS - right shift signed a:x known count (0..7) */
5540 /*-----------------------------------------------------------------*/
5542 AccAXRshS (char *x, int shCount)
5550 emitcode ("mov", "c,acc.7");
5551 AccAXRrl1 (x); // s->a:x
5555 emitcode ("mov", "c,acc.7");
5556 AccAXRrl1 (x); // s->a:x
5558 emitcode ("mov", "c,acc.7");
5559 AccAXRrl1 (x); // s->a:x
5564 case 5: // AAAAABBB:CCCCCDDD = a:x
5566 tlbl = newiTempLabel (NULL);
5567 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5569 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5571 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5573 emitcode ("anl", "a,#0x%02x",
5574 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5576 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5578 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5580 emitcode ("anl", "a,#0x%02x",
5581 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5583 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5585 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5587 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5589 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5590 emitcode ("orl", "a,#0x%02x",
5591 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5593 emitcode ("", "%05d$:", tlbl->key + 100);
5594 break; // SSSSAAAA:BBBCCCCC
5596 case 6: // AABBBBBB:CCDDDDDD
5598 tlbl = newiTempLabel (NULL);
5599 emitcode ("mov", "c,acc.7");
5600 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5602 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5604 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5606 emitcode ("anl", "a,#0x%02x",
5607 SRMask[shCount]); // 000000AA:BBBBBBCC
5609 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5610 emitcode ("orl", "a,#0x%02x",
5611 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5613 emitcode ("", "%05d$:", tlbl->key + 100);
5615 case 7: // ABBBBBBB:CDDDDDDD
5617 tlbl = newiTempLabel (NULL);
5618 emitcode ("mov", "c,acc.7"); // c = A
5620 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5622 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5624 emitcode ("anl", "a,#0x%02x",
5625 SRMask[shCount]); // 0000000A:BBBBBBBC
5627 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5628 emitcode ("orl", "a,#0x%02x",
5629 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5631 emitcode ("", "%05d$:", tlbl->key + 100);
5638 /*-----------------------------------------------------------------*/
5639 /* shiftL2Left2Result - shift left two bytes from left to result */
5640 /*-----------------------------------------------------------------*/
5642 shiftL2Left2Result (operand * left, int offl,
5643 operand * result, int offr, int shCount)
5645 if (sameRegs (AOP (result), AOP (left)) &&
5646 ((offl + MSB16) == offr))
5648 /* don't crash result[offr] */
5649 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5650 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5654 movLeft2Result (left, offl, result, offr, 0);
5655 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5657 /* ax << shCount (x = lsb(result)) */
5658 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5659 aopPut (AOP (result), "a", offr + MSB16);
5663 /*-----------------------------------------------------------------*/
5664 /* shiftR2Left2Result - shift right two bytes from left to result */
5665 /*-----------------------------------------------------------------*/
5667 shiftR2Left2Result (operand * left, int offl,
5668 operand * result, int offr,
5669 int shCount, int sign)
5671 if (sameRegs (AOP (result), AOP (left)) &&
5672 ((offl + MSB16) == offr))
5674 /* don't crash result[offr] */
5675 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5676 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5680 movLeft2Result (left, offl, result, offr, 0);
5681 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5683 /* a:x >> shCount (x = lsb(result)) */
5685 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5687 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5688 if (getDataSize (result) > 1)
5689 aopPut (AOP (result), "a", offr + MSB16);
5692 /*-----------------------------------------------------------------*/
5693 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5694 /*-----------------------------------------------------------------*/
5696 shiftLLeftOrResult (operand * left, int offl,
5697 operand * result, int offr, int shCount)
5699 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5700 /* shift left accumulator */
5702 /* or with result */
5703 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5704 /* back to result */
5705 aopPut (AOP (result), "a", offr);
5708 /*-----------------------------------------------------------------*/
5709 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5710 /*-----------------------------------------------------------------*/
5712 shiftRLeftOrResult (operand * left, int offl,
5713 operand * result, int offr, int shCount)
5715 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5716 /* shift right accumulator */
5718 /* or with result */
5719 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5720 /* back to result */
5721 aopPut (AOP (result), "a", offr);
5724 /*-----------------------------------------------------------------*/
5725 /* genlshOne - left shift a one byte quantity by known count */
5726 /*-----------------------------------------------------------------*/
5728 genlshOne (operand * result, operand * left, int shCount)
5730 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5733 /*-----------------------------------------------------------------*/
5734 /* genlshTwo - left shift two bytes by known amount != 0 */
5735 /*-----------------------------------------------------------------*/
5737 genlshTwo (operand * result, operand * left, int shCount)
5741 size = getDataSize (result);
5743 /* if shCount >= 8 */
5751 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5753 movLeft2Result (left, LSB, result, MSB16, 0);
5755 aopPut (AOP (result), zero, LSB);
5758 /* 1 <= shCount <= 7 */
5762 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5764 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5768 /*-----------------------------------------------------------------*/
5769 /* shiftLLong - shift left one long from left to result */
5770 /* offl = LSB or MSB16 */
5771 /*-----------------------------------------------------------------*/
5773 shiftLLong (operand * left, operand * result, int offr)
5776 int size = AOP_SIZE (result);
5778 if (size >= LSB + offr)
5780 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5782 emitcode ("add", "a,acc");
5783 if (sameRegs (AOP (left), AOP (result)) &&
5784 size >= MSB16 + offr && offr != LSB)
5785 emitcode ("xch", "a,%s",
5786 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5788 aopPut (AOP (result), "a", LSB + offr);
5791 if (size >= MSB16 + offr)
5793 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5795 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5798 emitcode ("rlc", "a");
5799 if (sameRegs (AOP (left), AOP (result)) &&
5800 size >= MSB24 + offr && offr != LSB)
5801 emitcode ("xch", "a,%s",
5802 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5804 aopPut (AOP (result), "a", MSB16 + offr);
5807 if (size >= MSB24 + offr)
5809 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5811 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5814 emitcode ("rlc", "a");
5815 if (sameRegs (AOP (left), AOP (result)) &&
5816 size >= MSB32 + offr && offr != LSB)
5817 emitcode ("xch", "a,%s",
5818 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5820 aopPut (AOP (result), "a", MSB24 + offr);
5823 if (size > MSB32 + offr)
5825 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5827 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5830 emitcode ("rlc", "a");
5831 aopPut (AOP (result), "a", MSB32 + offr);
5834 aopPut (AOP (result), zero, LSB);
5837 /*-----------------------------------------------------------------*/
5838 /* genlshFour - shift four byte by a known amount != 0 */
5839 /*-----------------------------------------------------------------*/
5841 genlshFour (operand * result, operand * left, int shCount)
5845 size = AOP_SIZE (result);
5847 /* if shifting more that 3 bytes */
5852 /* lowest order of left goes to the highest
5853 order of the destination */
5854 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5856 movLeft2Result (left, LSB, result, MSB32, 0);
5857 aopPut (AOP (result), zero, LSB);
5858 aopPut (AOP (result), zero, MSB16);
5859 aopPut (AOP (result), zero, MSB24);
5863 /* more than two bytes */
5864 else if (shCount >= 16)
5866 /* lower order two bytes goes to higher order two bytes */
5868 /* if some more remaining */
5870 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5873 movLeft2Result (left, MSB16, result, MSB32, 0);
5874 movLeft2Result (left, LSB, result, MSB24, 0);
5876 aopPut (AOP (result), zero, MSB16);
5877 aopPut (AOP (result), zero, LSB);
5881 /* if more than 1 byte */
5882 else if (shCount >= 8)
5884 /* lower order three bytes goes to higher order three bytes */
5889 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5891 movLeft2Result (left, LSB, result, MSB16, 0);
5897 movLeft2Result (left, MSB24, result, MSB32, 0);
5898 movLeft2Result (left, MSB16, result, MSB24, 0);
5899 movLeft2Result (left, LSB, result, MSB16, 0);
5900 aopPut (AOP (result), zero, LSB);
5902 else if (shCount == 1)
5903 shiftLLong (left, result, MSB16);
5906 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5907 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5908 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5909 aopPut (AOP (result), zero, LSB);
5914 /* 1 <= shCount <= 7 */
5915 else if (shCount <= 2)
5917 shiftLLong (left, result, LSB);
5919 shiftLLong (result, result, LSB);
5921 /* 3 <= shCount <= 7, optimize */
5924 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5925 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5926 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5930 /*-----------------------------------------------------------------*/
5931 /* genLeftShiftLiteral - left shifting by known count */
5932 /*-----------------------------------------------------------------*/
5934 genLeftShiftLiteral (operand * left,
5939 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5942 freeAsmop (right, NULL, ic, TRUE);
5944 aopOp (left, ic, FALSE);
5945 aopOp (result, ic, FALSE);
5947 size = getSize (operandType (result));
5950 emitcode ("; shift left ", "result %d, left %d", size,
5954 /* I suppose that the left size >= result size */
5959 movLeft2Result (left, size, result, size, 0);
5963 else if (shCount >= (size * 8))
5965 aopPut (AOP (result), zero, size);
5971 genlshOne (result, left, shCount);
5976 genlshTwo (result, left, shCount);
5980 genlshFour (result, left, shCount);
5984 freeAsmop (left, NULL, ic, TRUE);
5985 freeAsmop (result, NULL, ic, TRUE);
5988 /*-----------------------------------------------------------------*/
5989 /* genLeftShift - generates code for left shifting */
5990 /*-----------------------------------------------------------------*/
5992 genLeftShift (iCode * ic)
5994 operand *left, *right, *result;
5997 symbol *tlbl, *tlbl1;
5999 right = IC_RIGHT (ic);
6000 left = IC_LEFT (ic);
6001 result = IC_RESULT (ic);
6003 aopOp (right, ic, FALSE);
6005 /* if the shift count is known then do it
6006 as efficiently as possible */
6007 if (AOP_TYPE (right) == AOP_LIT)
6009 genLeftShiftLiteral (left, right, result, ic);
6013 /* shift count is unknown then we have to form
6014 a loop get the loop count in B : Note: we take
6015 only the lower order byte since shifting
6016 more that 32 bits make no sense anyway, ( the
6017 largest size of an object can be only 32 bits ) */
6019 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6020 emitcode ("inc", "b");
6021 freeAsmop (right, NULL, ic, TRUE);
6022 aopOp (left, ic, FALSE);
6023 aopOp (result, ic, FALSE);
6025 /* now move the left to the result if they are not the
6027 if (!sameRegs (AOP (left), AOP (result)) &&
6028 AOP_SIZE (result) > 1)
6031 size = AOP_SIZE (result);
6035 l = aopGet (AOP (left), offset, FALSE, TRUE);
6036 if (*l == '@' && (IS_AOP_PREG (result)))
6039 emitcode ("mov", "a,%s", l);
6040 aopPut (AOP (result), "a", offset);
6043 aopPut (AOP (result), l, offset);
6048 tlbl = newiTempLabel (NULL);
6049 size = AOP_SIZE (result);
6051 tlbl1 = newiTempLabel (NULL);
6053 /* if it is only one byte then */
6056 symbol *tlbl1 = newiTempLabel (NULL);
6058 l = aopGet (AOP (left), 0, FALSE, FALSE);
6060 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6061 emitcode ("", "%05d$:", tlbl->key + 100);
6062 emitcode ("add", "a,acc");
6063 emitcode ("", "%05d$:", tlbl1->key + 100);
6064 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6065 aopPut (AOP (result), "a", 0);
6069 reAdjustPreg (AOP (result));
6071 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6072 emitcode ("", "%05d$:", tlbl->key + 100);
6073 l = aopGet (AOP (result), offset, FALSE, FALSE);
6075 emitcode ("add", "a,acc");
6076 aopPut (AOP (result), "a", offset++);
6079 l = aopGet (AOP (result), offset, FALSE, FALSE);
6081 emitcode ("rlc", "a");
6082 aopPut (AOP (result), "a", offset++);
6084 reAdjustPreg (AOP (result));
6086 emitcode ("", "%05d$:", tlbl1->key + 100);
6087 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6089 freeAsmop (left, NULL, ic, TRUE);
6090 freeAsmop (result, NULL, ic, TRUE);
6093 /*-----------------------------------------------------------------*/
6094 /* genrshOne - right shift a one byte quantity by known count */
6095 /*-----------------------------------------------------------------*/
6097 genrshOne (operand * result, operand * left,
6098 int shCount, int sign)
6100 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6103 /*-----------------------------------------------------------------*/
6104 /* genrshTwo - right shift two bytes by known amount != 0 */
6105 /*-----------------------------------------------------------------*/
6107 genrshTwo (operand * result, operand * left,
6108 int shCount, int sign)
6110 /* if shCount >= 8 */
6115 shiftR1Left2Result (left, MSB16, result, LSB,
6118 movLeft2Result (left, MSB16, result, LSB, sign);
6119 addSign (result, MSB16, sign);
6122 /* 1 <= shCount <= 7 */
6124 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6127 /*-----------------------------------------------------------------*/
6128 /* shiftRLong - shift right one long from left to result */
6129 /* offl = LSB or MSB16 */
6130 /*-----------------------------------------------------------------*/
6132 shiftRLong (operand * left, int offl,
6133 operand * result, int sign)
6136 emitcode ("clr", "c");
6137 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6139 emitcode ("mov", "c,acc.7");
6140 emitcode ("rrc", "a");
6141 aopPut (AOP (result), "a", MSB32 - offl);
6143 /* add sign of "a" */
6144 addSign (result, MSB32, sign);
6146 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6147 emitcode ("rrc", "a");
6148 aopPut (AOP (result), "a", MSB24 - offl);
6150 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6151 emitcode ("rrc", "a");
6152 aopPut (AOP (result), "a", MSB16 - offl);
6156 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6157 emitcode ("rrc", "a");
6158 aopPut (AOP (result), "a", LSB);
6162 /*-----------------------------------------------------------------*/
6163 /* genrshFour - shift four byte by a known amount != 0 */
6164 /*-----------------------------------------------------------------*/
6166 genrshFour (operand * result, operand * left,
6167 int shCount, int sign)
6169 /* if shifting more that 3 bytes */
6174 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6176 movLeft2Result (left, MSB32, result, LSB, sign);
6177 addSign (result, MSB16, sign);
6179 else if (shCount >= 16)
6183 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6186 movLeft2Result (left, MSB24, result, LSB, 0);
6187 movLeft2Result (left, MSB32, result, MSB16, sign);
6189 addSign (result, MSB24, sign);
6191 else if (shCount >= 8)
6195 shiftRLong (left, MSB16, result, sign);
6196 else if (shCount == 0)
6198 movLeft2Result (left, MSB16, result, LSB, 0);
6199 movLeft2Result (left, MSB24, result, MSB16, 0);
6200 movLeft2Result (left, MSB32, result, MSB24, sign);
6201 addSign (result, MSB32, sign);
6205 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6206 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6207 /* the last shift is signed */
6208 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6209 addSign (result, MSB32, sign);
6213 { /* 1 <= shCount <= 7 */
6216 shiftRLong (left, LSB, result, sign);
6218 shiftRLong (result, LSB, result, sign);
6222 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6223 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6224 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6229 /*-----------------------------------------------------------------*/
6230 /* genRightShiftLiteral - right shifting by known count */
6231 /*-----------------------------------------------------------------*/
6233 genRightShiftLiteral (operand * left,
6239 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6242 freeAsmop (right, NULL, ic, TRUE);
6244 aopOp (left, ic, FALSE);
6245 aopOp (result, ic, FALSE);
6248 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6252 size = getDataSize (left);
6253 /* test the LEFT size !!! */
6255 /* I suppose that the left size >= result size */
6258 size = getDataSize (result);
6260 movLeft2Result (left, size, result, size, 0);
6263 else if (shCount >= (size * 8))
6266 /* get sign in acc.7 */
6267 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6268 addSign (result, LSB, sign);
6275 genrshOne (result, left, shCount, sign);
6279 genrshTwo (result, left, shCount, sign);
6283 genrshFour (result, left, shCount, sign);
6289 freeAsmop (left, NULL, ic, TRUE);
6290 freeAsmop (result, NULL, ic, TRUE);
6294 /*-----------------------------------------------------------------*/
6295 /* genSignedRightShift - right shift of signed number */
6296 /*-----------------------------------------------------------------*/
6298 genSignedRightShift (iCode * ic)
6300 operand *right, *left, *result;
6303 symbol *tlbl, *tlbl1;
6305 /* we do it the hard way put the shift count in b
6306 and loop thru preserving the sign */
6308 right = IC_RIGHT (ic);
6309 left = IC_LEFT (ic);
6310 result = IC_RESULT (ic);
6312 aopOp (right, ic, FALSE);
6315 if (AOP_TYPE (right) == AOP_LIT)
6317 genRightShiftLiteral (left, right, result, ic, 1);
6320 /* shift count is unknown then we have to form
6321 a loop get the loop count in B : Note: we take
6322 only the lower order byte since shifting
6323 more that 32 bits make no sense anyway, ( the
6324 largest size of an object can be only 32 bits ) */
6326 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6327 emitcode ("inc", "b");
6328 freeAsmop (right, NULL, ic, TRUE);
6329 aopOp (left, ic, FALSE);
6330 aopOp (result, ic, FALSE);
6332 /* now move the left to the result if they are not the
6334 if (!sameRegs (AOP (left), AOP (result)) &&
6335 AOP_SIZE (result) > 1)
6338 size = AOP_SIZE (result);
6342 l = aopGet (AOP (left), offset, FALSE, TRUE);
6343 if (*l == '@' && IS_AOP_PREG (result))
6346 emitcode ("mov", "a,%s", l);
6347 aopPut (AOP (result), "a", offset);
6350 aopPut (AOP (result), l, offset);
6355 /* mov the highest order bit to OVR */
6356 tlbl = newiTempLabel (NULL);
6357 tlbl1 = newiTempLabel (NULL);
6359 size = AOP_SIZE (result);
6361 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6362 emitcode ("rlc", "a");
6363 emitcode ("mov", "ov,c");
6364 /* if it is only one byte then */
6367 l = aopGet (AOP (left), 0, FALSE, FALSE);
6369 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6370 emitcode ("", "%05d$:", tlbl->key + 100);
6371 emitcode ("mov", "c,ov");
6372 emitcode ("rrc", "a");
6373 emitcode ("", "%05d$:", tlbl1->key + 100);
6374 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6375 aopPut (AOP (result), "a", 0);
6379 reAdjustPreg (AOP (result));
6380 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6381 emitcode ("", "%05d$:", tlbl->key + 100);
6382 emitcode ("mov", "c,ov");
6385 l = aopGet (AOP (result), offset, FALSE, FALSE);
6387 emitcode ("rrc", "a");
6388 aopPut (AOP (result), "a", offset--);
6390 reAdjustPreg (AOP (result));
6391 emitcode ("", "%05d$:", tlbl1->key + 100);
6392 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6395 freeAsmop (left, NULL, ic, TRUE);
6396 freeAsmop (result, NULL, ic, TRUE);
6399 /*-----------------------------------------------------------------*/
6400 /* genRightShift - generate code for right shifting */
6401 /*-----------------------------------------------------------------*/
6403 genRightShift (iCode * ic)
6405 operand *right, *left, *result;
6409 symbol *tlbl, *tlbl1;
6411 /* if signed then we do it the hard way preserve the
6412 sign bit moving it inwards */
6413 retype = getSpec (operandType (IC_RESULT (ic)));
6415 if (!SPEC_USIGN (retype))
6417 genSignedRightShift (ic);
6421 /* signed & unsigned types are treated the same : i.e. the
6422 signed is NOT propagated inwards : quoting from the
6423 ANSI - standard : "for E1 >> E2, is equivalent to division
6424 by 2**E2 if unsigned or if it has a non-negative value,
6425 otherwise the result is implementation defined ", MY definition
6426 is that the sign does not get propagated */
6428 right = IC_RIGHT (ic);
6429 left = IC_LEFT (ic);
6430 result = IC_RESULT (ic);
6432 aopOp (right, ic, FALSE);
6434 /* if the shift count is known then do it
6435 as efficiently as possible */
6436 if (AOP_TYPE (right) == AOP_LIT)
6438 genRightShiftLiteral (left, right, result, ic, 0);
6442 /* shift count is unknown then we have to form
6443 a loop get the loop count in B : Note: we take
6444 only the lower order byte since shifting
6445 more that 32 bits make no sense anyway, ( the
6446 largest size of an object can be only 32 bits ) */
6448 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6449 emitcode ("inc", "b");
6450 freeAsmop (right, NULL, ic, TRUE);
6451 aopOp (left, ic, FALSE);
6452 aopOp (result, ic, FALSE);
6454 /* now move the left to the result if they are not the
6456 if (!sameRegs (AOP (left), AOP (result)) &&
6457 AOP_SIZE (result) > 1)
6460 size = AOP_SIZE (result);
6464 l = aopGet (AOP (left), offset, FALSE, TRUE);
6465 if (*l == '@' && IS_AOP_PREG (result))
6468 emitcode ("mov", "a,%s", l);
6469 aopPut (AOP (result), "a", offset);
6472 aopPut (AOP (result), l, offset);
6477 tlbl = newiTempLabel (NULL);
6478 tlbl1 = newiTempLabel (NULL);
6479 size = AOP_SIZE (result);
6482 /* if it is only one byte then */
6485 l = aopGet (AOP (left), 0, FALSE, FALSE);
6487 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6488 emitcode ("", "%05d$:", tlbl->key + 100);
6490 emitcode ("rrc", "a");
6491 emitcode ("", "%05d$:", tlbl1->key + 100);
6492 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6493 aopPut (AOP (result), "a", 0);
6497 reAdjustPreg (AOP (result));
6498 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6499 emitcode ("", "%05d$:", tlbl->key + 100);
6503 l = aopGet (AOP (result), offset, FALSE, FALSE);
6505 emitcode ("rrc", "a");
6506 aopPut (AOP (result), "a", offset--);
6508 reAdjustPreg (AOP (result));
6510 emitcode ("", "%05d$:", tlbl1->key + 100);
6511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6514 freeAsmop (left, NULL, ic, TRUE);
6515 freeAsmop (result, NULL, ic, TRUE);
6518 /*-----------------------------------------------------------------*/
6519 /* genUnpackBits - generates code for unpacking bits */
6520 /*-----------------------------------------------------------------*/
6522 genUnpackBits (operand * result, char *rname, int ptype)
6530 etype = getSpec (operandType (result));
6531 rsize = getSize (operandType (result));
6532 /* read the first byte */
6538 emitcode ("mov", "a,@%s", rname);
6542 emitcode ("movx", "a,@%s", rname);
6546 emitcode ("movx", "a,@dptr");
6550 emitcode ("clr", "a");
6551 emitcode ("movc", "a,%s", "@a+dptr");
6555 emitcode ("lcall", "__gptrget");
6559 rlen = SPEC_BLEN (etype);
6561 /* if we have bitdisplacement then it fits */
6562 /* into this byte completely or if length is */
6563 /* less than a byte */
6564 if ((shCnt = SPEC_BSTR (etype)) ||
6565 (SPEC_BLEN (etype) <= 8))
6568 /* shift right acc */
6571 emitcode ("anl", "a,#0x%02x",
6572 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6573 aopPut (AOP (result), "a", offset++);
6577 /* bit field did not fit in a byte */
6578 aopPut (AOP (result), "a", offset++);
6587 emitcode ("inc", "%s", rname);
6588 emitcode ("mov", "a,@%s", rname);
6592 emitcode ("inc", "%s", rname);
6593 emitcode ("movx", "a,@%s", rname);
6597 emitcode ("inc", "dptr");
6598 emitcode ("movx", "a,@dptr");
6602 emitcode ("clr", "a");
6603 emitcode ("inc", "dptr");
6604 emitcode ("movc", "a", "@a+dptr");
6608 emitcode ("inc", "dptr");
6609 emitcode ("lcall", "__gptrget");
6614 /* if we are done */
6618 aopPut (AOP (result), "a", offset++);
6624 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6626 aopPut (AOP (result), "a", offset++);
6634 aopPut (AOP (result), zero, offset++);
6640 /*-----------------------------------------------------------------*/
6641 /* genDataPointerGet - generates code when ptr offset is known */
6642 /*-----------------------------------------------------------------*/
6644 genDataPointerGet (operand * left,
6650 int size, offset = 0;
6651 aopOp (result, ic, TRUE);
6653 /* get the string representation of the name */
6654 l = aopGet (AOP (left), 0, FALSE, TRUE);
6655 size = AOP_SIZE (result);
6659 sprintf (buffer, "(%s + %d)", l + 1, offset);
6661 sprintf (buffer, "%s", l + 1);
6662 aopPut (AOP (result), buffer, offset++);
6665 freeAsmop (left, NULL, ic, TRUE);
6666 freeAsmop (result, NULL, ic, TRUE);
6669 /*-----------------------------------------------------------------*/
6670 /* genNearPointerGet - emitcode for near pointer fetch */
6671 /*-----------------------------------------------------------------*/
6673 genNearPointerGet (operand * left,
6681 sym_link *rtype, *retype;
6682 sym_link *ltype = operandType (left);
6685 rtype = operandType (result);
6686 retype = getSpec (rtype);
6688 aopOp (left, ic, FALSE);
6690 /* if left is rematerialisable and
6691 result is not bit variable type and
6692 the left is pointer to data space i.e
6693 lower 128 bytes of space */
6694 if (AOP_TYPE (left) == AOP_IMMD &&
6695 !IS_BITVAR (retype) &&
6696 DCL_TYPE (ltype) == POINTER)
6698 genDataPointerGet (left, result, ic);
6702 /* if the value is already in a pointer register
6703 then don't need anything more */
6704 if (!AOP_INPREG (AOP (left)))
6706 /* otherwise get a free pointer register */
6708 preg = getFreePtr (ic, &aop, FALSE);
6709 emitcode ("mov", "%s,%s",
6711 aopGet (AOP (left), 0, FALSE, TRUE));
6715 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6717 aopOp (result, ic, FALSE);
6719 /* if bitfield then unpack the bits */
6720 if (IS_BITVAR (retype))
6721 genUnpackBits (result, rname, POINTER);
6724 /* we have can just get the values */
6725 int size = AOP_SIZE (result);
6730 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6733 emitcode ("mov", "a,@%s", rname);
6734 aopPut (AOP (result), "a", offset);
6738 sprintf (buffer, "@%s", rname);
6739 aopPut (AOP (result), buffer, offset);
6743 emitcode ("inc", "%s", rname);
6747 /* now some housekeeping stuff */
6748 if (aop) /* we had to allocate for this iCode */
6750 if (pi) { /* post increment present */
6751 aopPut(AOP ( left ),rname,0);
6753 freeAsmop (NULL, aop, ic, TRUE);
6757 /* we did not allocate which means left
6758 already in a pointer register, then
6759 if size > 0 && this could be used again
6760 we have to point it back to where it
6762 if ((AOP_SIZE (result) > 1 &&
6763 !OP_SYMBOL (left)->remat &&
6764 (OP_SYMBOL (left)->liveTo > ic->seq ||
6768 int size = AOP_SIZE (result) - 1;
6770 emitcode ("dec", "%s", rname);
6775 freeAsmop (left, NULL, ic, TRUE);
6776 freeAsmop (result, NULL, ic, TRUE);
6777 if (pi) pi->generated = 1;
6780 /*-----------------------------------------------------------------*/
6781 /* genPagedPointerGet - emitcode for paged pointer fetch */
6782 /*-----------------------------------------------------------------*/
6784 genPagedPointerGet (operand * left,
6792 sym_link *rtype, *retype;
6794 rtype = operandType (result);
6795 retype = getSpec (rtype);
6797 aopOp (left, ic, FALSE);
6799 /* if the value is already in a pointer register
6800 then don't need anything more */
6801 if (!AOP_INPREG (AOP (left)))
6803 /* otherwise get a free pointer register */
6805 preg = getFreePtr (ic, &aop, FALSE);
6806 emitcode ("mov", "%s,%s",
6808 aopGet (AOP (left), 0, FALSE, TRUE));
6812 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6814 aopOp (result, ic, FALSE);
6816 /* if bitfield then unpack the bits */
6817 if (IS_BITVAR (retype))
6818 genUnpackBits (result, rname, PPOINTER);
6821 /* we have can just get the values */
6822 int size = AOP_SIZE (result);
6828 emitcode ("movx", "a,@%s", rname);
6829 aopPut (AOP (result), "a", offset);
6834 emitcode ("inc", "%s", rname);
6838 /* now some housekeeping stuff */
6839 if (aop) /* we had to allocate for this iCode */
6841 if (pi) aopPut ( AOP (left), rname, 0);
6842 freeAsmop (NULL, aop, ic, TRUE);
6846 /* we did not allocate which means left
6847 already in a pointer register, then
6848 if size > 0 && this could be used again
6849 we have to point it back to where it
6851 if ((AOP_SIZE (result) > 1 &&
6852 !OP_SYMBOL (left)->remat &&
6853 (OP_SYMBOL (left)->liveTo > ic->seq ||
6857 int size = AOP_SIZE (result) - 1;
6859 emitcode ("dec", "%s", rname);
6864 freeAsmop (left, NULL, ic, TRUE);
6865 freeAsmop (result, NULL, ic, TRUE);
6866 if (pi) pi->generated = 1;
6870 /*-----------------------------------------------------------------*/
6871 /* genFarPointerGet - gget value from far space */
6872 /*-----------------------------------------------------------------*/
6874 genFarPointerGet (operand * left,
6875 operand * result, iCode * ic, iCode * pi)
6878 sym_link *retype = getSpec (operandType (result));
6880 aopOp (left, ic, FALSE);
6882 /* if the operand is already in dptr
6883 then we do nothing else we move the value to dptr */
6884 if (AOP_TYPE (left) != AOP_STR)
6886 /* if this is remateriazable */
6887 if (AOP_TYPE (left) == AOP_IMMD)
6888 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6890 { /* we need to get it byte by byte */
6891 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6892 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6895 /* so dptr know contains the address */
6896 aopOp (result, ic, FALSE);
6898 /* if bit then unpack */
6899 if (IS_BITVAR (retype))
6900 genUnpackBits (result, "dptr", FPOINTER);
6903 size = AOP_SIZE (result);
6908 emitcode ("movx", "a,@dptr");
6909 aopPut (AOP (result), "a", offset++);
6911 emitcode ("inc", "dptr");
6915 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6916 aopPut ( AOP (left), "dpl", 0);
6917 aopPut ( AOP (left), "dph", 1);
6920 freeAsmop (left, NULL, ic, TRUE);
6921 freeAsmop (result, NULL, ic, TRUE);
6924 /*-----------------------------------------------------------------*/
6925 /* genCodePointerGet - gget value from code space */
6926 /*-----------------------------------------------------------------*/
6928 genCodePointerGet (operand * left,
6929 operand * result, iCode * ic, iCode *pi)
6932 sym_link *retype = getSpec (operandType (result));
6934 aopOp (left, ic, FALSE);
6936 /* if the operand is already in dptr
6937 then we do nothing else we move the value to dptr */
6938 if (AOP_TYPE (left) != AOP_STR)
6940 /* if this is remateriazable */
6941 if (AOP_TYPE (left) == AOP_IMMD)
6942 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6944 { /* we need to get it byte by byte */
6945 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6946 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6949 /* so dptr know contains the address */
6950 aopOp (result, ic, FALSE);
6952 /* if bit then unpack */
6953 if (IS_BITVAR (retype))
6954 genUnpackBits (result, "dptr", CPOINTER);
6957 size = AOP_SIZE (result);
6962 emitcode ("clr", "a");
6963 emitcode ("movc", "a,@a+dptr");
6964 aopPut (AOP (result), "a", offset++);
6966 emitcode ("inc", "dptr");
6970 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6971 aopPut ( AOP (left), "dpl", 0);
6972 aopPut ( AOP (left), "dph", 1);
6975 freeAsmop (left, NULL, ic, TRUE);
6976 freeAsmop (result, NULL, ic, TRUE);
6979 /*-----------------------------------------------------------------*/
6980 /* genGenPointerGet - gget value from generic pointer space */
6981 /*-----------------------------------------------------------------*/
6983 genGenPointerGet (operand * left,
6984 operand * result, iCode * ic, iCode *pi)
6987 sym_link *retype = getSpec (operandType (result));
6989 aopOp (left, ic, FALSE);
6991 /* if the operand is already in dptr
6992 then we do nothing else we move the value to dptr */
6993 if (AOP_TYPE (left) != AOP_STR)
6995 /* if this is remateriazable */
6996 if (AOP_TYPE (left) == AOP_IMMD)
6998 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6999 emitcode ("mov", "b,#%d", pointerCode (retype));
7002 { /* we need to get it byte by byte */
7003 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7004 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7005 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7008 /* so dptr know contains the address */
7009 aopOp (result, ic, FALSE);
7011 /* if bit then unpack */
7012 if (IS_BITVAR (retype))
7013 genUnpackBits (result, "dptr", GPOINTER);
7016 size = AOP_SIZE (result);
7021 emitcode ("lcall", "__gptrget");
7022 aopPut (AOP (result), "a", offset++);
7024 emitcode ("inc", "dptr");
7028 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7029 aopPut ( AOP (left), "dpl", 0);
7030 aopPut ( AOP (left), "dph", 1);
7033 freeAsmop (left, NULL, ic, TRUE);
7034 freeAsmop (result, NULL, ic, TRUE);
7037 /*-----------------------------------------------------------------*/
7038 /* genPointerGet - generate code for pointer get */
7039 /*-----------------------------------------------------------------*/
7041 genPointerGet (iCode * ic, iCode *pi)
7043 operand *left, *result;
7044 sym_link *type, *etype;
7047 left = IC_LEFT (ic);
7048 result = IC_RESULT (ic);
7050 /* depending on the type of pointer we need to
7051 move it to the correct pointer register */
7052 type = operandType (left);
7053 etype = getSpec (type);
7054 /* if left is of type of pointer then it is simple */
7055 if (IS_PTR (type) && !IS_FUNC (type->next))
7056 p_type = DCL_TYPE (type);
7059 /* we have to go by the storage class */
7060 p_type = PTR_TYPE (SPEC_OCLS (etype));
7063 /* now that we have the pointer type we assign
7064 the pointer values */
7070 genNearPointerGet (left, result, ic, pi);
7074 genPagedPointerGet (left, result, ic, pi);
7078 genFarPointerGet (left, result, ic, pi);
7082 genCodePointerGet (left, result, ic, pi);
7086 genGenPointerGet (left, result, ic, pi);
7092 /*-----------------------------------------------------------------*/
7093 /* genPackBits - generates code for packed bit storage */
7094 /*-----------------------------------------------------------------*/
7096 genPackBits (sym_link * etype,
7098 char *rname, int p_type)
7106 blen = SPEC_BLEN (etype);
7107 bstr = SPEC_BSTR (etype);
7109 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7112 /* if the bit lenth is less than or */
7113 /* it exactly fits a byte then */
7114 if (SPEC_BLEN (etype) <= 8)
7116 shCount = SPEC_BSTR (etype);
7118 /* shift left acc */
7121 if (SPEC_BLEN (etype) < 8)
7122 { /* if smaller than a byte */
7128 emitcode ("mov", "b,a");
7129 emitcode ("mov", "a,@%s", rname);
7133 emitcode ("mov", "b,a");
7134 emitcode ("movx", "a,@dptr");
7138 emitcode ("push", "b");
7139 emitcode ("push", "acc");
7140 emitcode ("lcall", "__gptrget");
7141 emitcode ("pop", "b");
7145 emitcode ("anl", "a,#0x%02x", (unsigned char)
7146 ((unsigned char) (0xFF << (blen + bstr)) |
7147 (unsigned char) (0xFF >> (8 - bstr))));
7148 emitcode ("orl", "a,b");
7149 if (p_type == GPOINTER)
7150 emitcode ("pop", "b");
7157 emitcode ("mov", "@%s,a", rname);
7161 emitcode ("movx", "@dptr,a");
7165 emitcode ("lcall", "__gptrput");
7170 if (SPEC_BLEN (etype) <= 8)
7173 emitcode ("inc", "%s", rname);
7174 rLen = SPEC_BLEN (etype);
7176 /* now generate for lengths greater than one byte */
7180 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7192 emitcode ("mov", "@%s,a", rname);
7195 emitcode ("mov", "@%s,%s", rname, l);
7200 emitcode ("movx", "@dptr,a");
7205 emitcode ("lcall", "__gptrput");
7208 emitcode ("inc", "%s", rname);
7213 /* last last was not complete */
7216 /* save the byte & read byte */
7220 emitcode ("mov", "b,a");
7221 emitcode ("mov", "a,@%s", rname);
7225 emitcode ("mov", "b,a");
7226 emitcode ("movx", "a,@dptr");
7230 emitcode ("push", "b");
7231 emitcode ("push", "acc");
7232 emitcode ("lcall", "__gptrget");
7233 emitcode ("pop", "b");
7237 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7238 emitcode ("orl", "a,b");
7241 if (p_type == GPOINTER)
7242 emitcode ("pop", "b");
7248 emitcode ("mov", "@%s,a", rname);
7252 emitcode ("movx", "@dptr,a");
7256 emitcode ("lcall", "__gptrput");
7260 /*-----------------------------------------------------------------*/
7261 /* genDataPointerSet - remat pointer to data space */
7262 /*-----------------------------------------------------------------*/
7264 genDataPointerSet (operand * right,
7268 int size, offset = 0;
7269 char *l, buffer[256];
7271 aopOp (right, ic, FALSE);
7273 l = aopGet (AOP (result), 0, FALSE, TRUE);
7274 size = AOP_SIZE (right);
7278 sprintf (buffer, "(%s + %d)", l + 1, offset);
7280 sprintf (buffer, "%s", l + 1);
7281 emitcode ("mov", "%s,%s", buffer,
7282 aopGet (AOP (right), offset++, FALSE, FALSE));
7285 freeAsmop (right, NULL, ic, TRUE);
7286 freeAsmop (result, NULL, ic, TRUE);
7289 /*-----------------------------------------------------------------*/
7290 /* genNearPointerSet - emitcode for near pointer put */
7291 /*-----------------------------------------------------------------*/
7293 genNearPointerSet (operand * right,
7301 sym_link *retype, *letype;
7302 sym_link *ptype = operandType (result);
7304 retype = getSpec (operandType (right));
7305 letype = getSpec (ptype);
7306 aopOp (result, ic, FALSE);
7308 /* if the result is rematerializable &
7309 in data space & not a bit variable */
7310 if (AOP_TYPE (result) == AOP_IMMD &&
7311 DCL_TYPE (ptype) == POINTER &&
7312 !IS_BITVAR (retype) &&
7313 !IS_BITVAR (letype))
7315 genDataPointerSet (right, result, ic);
7319 /* if the value is already in a pointer register
7320 then don't need anything more */
7321 if (!AOP_INPREG (AOP (result)))
7323 /* otherwise get a free pointer register */
7325 preg = getFreePtr (ic, &aop, FALSE);
7326 emitcode ("mov", "%s,%s",
7328 aopGet (AOP (result), 0, FALSE, TRUE));
7332 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7334 aopOp (right, ic, FALSE);
7336 /* if bitfield then unpack the bits */
7337 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7338 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7341 /* we have can just get the values */
7342 int size = AOP_SIZE (right);
7347 l = aopGet (AOP (right), offset, FALSE, TRUE);
7351 emitcode ("mov", "@%s,a", rname);
7354 emitcode ("mov", "@%s,%s", rname, l);
7356 emitcode ("inc", "%s", rname);
7361 /* now some housekeeping stuff */
7362 if (aop) /* we had to allocate for this iCode */
7364 if (pi) aopPut (AOP (result),rname,0);
7365 freeAsmop (NULL, aop, ic, TRUE);
7369 /* we did not allocate which means left
7370 already in a pointer register, then
7371 if size > 0 && this could be used again
7372 we have to point it back to where it
7374 if ((AOP_SIZE (right) > 1 &&
7375 !OP_SYMBOL (result)->remat &&
7376 (OP_SYMBOL (result)->liveTo > ic->seq ||
7380 int size = AOP_SIZE (right) - 1;
7382 emitcode ("dec", "%s", rname);
7387 if (pi) pi->generated = 1;
7388 freeAsmop (result, NULL, ic, TRUE);
7389 freeAsmop (right, NULL, ic, TRUE);
7392 /*-----------------------------------------------------------------*/
7393 /* genPagedPointerSet - emitcode for Paged pointer put */
7394 /*-----------------------------------------------------------------*/
7396 genPagedPointerSet (operand * right,
7404 sym_link *retype, *letype;
7406 retype = getSpec (operandType (right));
7407 letype = getSpec (operandType (result));
7409 aopOp (result, ic, FALSE);
7411 /* if the value is already in a pointer register
7412 then don't need anything more */
7413 if (!AOP_INPREG (AOP (result)))
7415 /* otherwise get a free pointer register */
7417 preg = getFreePtr (ic, &aop, FALSE);
7418 emitcode ("mov", "%s,%s",
7420 aopGet (AOP (result), 0, FALSE, TRUE));
7424 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7426 aopOp (right, ic, FALSE);
7428 /* if bitfield then unpack the bits */
7429 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7430 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7433 /* we have can just get the values */
7434 int size = AOP_SIZE (right);
7439 l = aopGet (AOP (right), offset, FALSE, TRUE);
7442 emitcode ("movx", "@%s,a", rname);
7445 emitcode ("inc", "%s", rname);
7451 /* now some housekeeping stuff */
7452 if (aop) /* we had to allocate for this iCode */
7454 if (pi) aopPut (AOP (result),rname,0);
7455 freeAsmop (NULL, aop, ic, TRUE);
7459 /* we did not allocate which means left
7460 already in a pointer register, then
7461 if size > 0 && this could be used again
7462 we have to point it back to where it
7464 if (AOP_SIZE (right) > 1 &&
7465 !OP_SYMBOL (result)->remat &&
7466 (OP_SYMBOL (result)->liveTo > ic->seq ||
7469 int size = AOP_SIZE (right) - 1;
7471 emitcode ("dec", "%s", rname);
7476 if (pi) pi->generated = 1;
7477 freeAsmop (result, NULL, ic, TRUE);
7478 freeAsmop (right, NULL, ic, TRUE);
7483 /*-----------------------------------------------------------------*/
7484 /* genFarPointerSet - set value from far space */
7485 /*-----------------------------------------------------------------*/
7487 genFarPointerSet (operand * right,
7488 operand * result, iCode * ic, iCode * pi)
7491 sym_link *retype = getSpec (operandType (right));
7492 sym_link *letype = getSpec (operandType (result));
7493 aopOp (result, ic, FALSE);
7495 /* if the operand is already in dptr
7496 then we do nothing else we move the value to dptr */
7497 if (AOP_TYPE (result) != AOP_STR)
7499 /* if this is remateriazable */
7500 if (AOP_TYPE (result) == AOP_IMMD)
7501 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7503 { /* we need to get it byte by byte */
7504 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7505 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7508 /* so dptr know contains the address */
7509 aopOp (right, ic, FALSE);
7511 /* if bit then unpack */
7512 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7513 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7516 size = AOP_SIZE (right);
7521 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7523 emitcode ("movx", "@dptr,a");
7525 emitcode ("inc", "dptr");
7528 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7529 aopPut (AOP(result),"dpl",0);
7530 aopPut (AOP(result),"dph",1);
7533 freeAsmop (result, NULL, ic, TRUE);
7534 freeAsmop (right, NULL, ic, TRUE);
7537 /*-----------------------------------------------------------------*/
7538 /* genGenPointerSet - set value from generic pointer space */
7539 /*-----------------------------------------------------------------*/
7541 genGenPointerSet (operand * right,
7542 operand * result, iCode * ic, iCode * pi)
7545 sym_link *retype = getSpec (operandType (right));
7546 sym_link *letype = getSpec (operandType (result));
7548 aopOp (result, ic, FALSE);
7550 /* if the operand is already in dptr
7551 then we do nothing else we move the value to dptr */
7552 if (AOP_TYPE (result) != AOP_STR)
7554 /* if this is remateriazable */
7555 if (AOP_TYPE (result) == AOP_IMMD)
7557 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7558 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7561 { /* we need to get it byte by byte */
7562 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7563 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7564 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7567 /* so dptr know contains the address */
7568 aopOp (right, ic, FALSE);
7570 /* if bit then unpack */
7571 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7572 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7575 size = AOP_SIZE (right);
7580 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7582 emitcode ("lcall", "__gptrput");
7584 emitcode ("inc", "dptr");
7588 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7589 aopPut (AOP(result),"dpl",0);
7590 aopPut (AOP(result),"dph",1);
7593 freeAsmop (result, NULL, ic, TRUE);
7594 freeAsmop (right, NULL, ic, TRUE);
7597 /*-----------------------------------------------------------------*/
7598 /* genPointerSet - stores the value into a pointer location */
7599 /*-----------------------------------------------------------------*/
7601 genPointerSet (iCode * ic, iCode *pi)
7603 operand *right, *result;
7604 sym_link *type, *etype;
7607 right = IC_RIGHT (ic);
7608 result = IC_RESULT (ic);
7610 /* depending on the type of pointer we need to
7611 move it to the correct pointer register */
7612 type = operandType (result);
7613 etype = getSpec (type);
7614 /* if left is of type of pointer then it is simple */
7615 if (IS_PTR (type) && !IS_FUNC (type->next))
7617 p_type = DCL_TYPE (type);
7621 /* we have to go by the storage class */
7622 p_type = PTR_TYPE (SPEC_OCLS (etype));
7625 /* now that we have the pointer type we assign
7626 the pointer values */
7632 genNearPointerSet (right, result, ic, pi);
7636 genPagedPointerSet (right, result, ic, pi);
7640 genFarPointerSet (right, result, ic, pi);
7644 genGenPointerSet (right, result, ic, pi);
7650 /*-----------------------------------------------------------------*/
7651 /* genIfx - generate code for Ifx statement */
7652 /*-----------------------------------------------------------------*/
7654 genIfx (iCode * ic, iCode * popIc)
7656 operand *cond = IC_COND (ic);
7659 aopOp (cond, ic, FALSE);
7661 /* get the value into acc */
7662 if (AOP_TYPE (cond) != AOP_CRY)
7666 /* the result is now in the accumulator */
7667 freeAsmop (cond, NULL, ic, TRUE);
7669 /* if there was something to be popped then do it */
7673 /* if the condition is a bit variable */
7674 if (isbit && IS_ITEMP (cond) &&
7676 genIfxJump (ic, SPIL_LOC (cond)->rname);
7677 else if (isbit && !IS_ITEMP (cond))
7678 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7680 genIfxJump (ic, "a");
7685 /*-----------------------------------------------------------------*/
7686 /* genAddrOf - generates code for address of */
7687 /*-----------------------------------------------------------------*/
7689 genAddrOf (iCode * ic)
7691 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7694 aopOp (IC_RESULT (ic), ic, FALSE);
7696 /* if the operand is on the stack then we
7697 need to get the stack offset of this
7701 /* if it has an offset then we need to compute
7705 emitcode ("mov", "a,_bp");
7706 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7707 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7711 /* we can just move _bp */
7712 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7714 /* fill the result with zero */
7715 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7720 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7726 /* object not on stack then we need the name */
7727 size = AOP_SIZE (IC_RESULT (ic));
7732 char s[SDCC_NAME_MAX];
7734 sprintf (s, "#(%s >> %d)",
7738 sprintf (s, "#%s", sym->rname);
7739 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7743 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7747 /*-----------------------------------------------------------------*/
7748 /* genFarFarAssign - assignment when both are in far space */
7749 /*-----------------------------------------------------------------*/
7751 genFarFarAssign (operand * result, operand * right, iCode * ic)
7753 int size = AOP_SIZE (right);
7756 /* first push the right side on to the stack */
7759 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7761 emitcode ("push", "acc");
7764 freeAsmop (right, NULL, ic, FALSE);
7765 /* now assign DPTR to result */
7766 aopOp (result, ic, FALSE);
7767 size = AOP_SIZE (result);
7770 emitcode ("pop", "acc");
7771 aopPut (AOP (result), "a", --offset);
7773 freeAsmop (result, NULL, ic, FALSE);
7777 /*-----------------------------------------------------------------*/
7778 /* genAssign - generate code for assignment */
7779 /*-----------------------------------------------------------------*/
7781 genAssign (iCode * ic)
7783 operand *result, *right;
7785 unsigned long lit = 0L;
7787 result = IC_RESULT (ic);
7788 right = IC_RIGHT (ic);
7790 /* if they are the same */
7791 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7794 aopOp (right, ic, FALSE);
7796 /* special case both in far space */
7797 if (AOP_TYPE (right) == AOP_DPTR &&
7798 IS_TRUE_SYMOP (result) &&
7799 isOperandInFarSpace (result))
7802 genFarFarAssign (result, right, ic);
7806 aopOp (result, ic, TRUE);
7808 /* if they are the same registers */
7809 if (sameRegs (AOP (right), AOP (result)))
7812 /* if the result is a bit */
7813 if (AOP_TYPE (result) == AOP_CRY)
7816 /* if the right size is a literal then
7817 we know what the value is */
7818 if (AOP_TYPE (right) == AOP_LIT)
7820 if (((int) operandLitValue (right)))
7821 aopPut (AOP (result), one, 0);
7823 aopPut (AOP (result), zero, 0);
7827 /* the right is also a bit variable */
7828 if (AOP_TYPE (right) == AOP_CRY)
7830 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7831 aopPut (AOP (result), "c", 0);
7837 aopPut (AOP (result), "a", 0);
7841 /* bit variables done */
7843 size = AOP_SIZE (result);
7845 if (AOP_TYPE (right) == AOP_LIT)
7846 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7848 (AOP_TYPE (result) != AOP_REG) &&
7849 (AOP_TYPE (right) == AOP_LIT) &&
7850 !IS_FLOAT (operandType (right)) &&
7853 emitcode ("clr", "a");
7856 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7857 aopPut (AOP (result), "a", size);
7859 aopPut (AOP (result),
7860 aopGet (AOP (right), size, FALSE, FALSE),
7868 aopPut (AOP (result),
7869 aopGet (AOP (right), offset, FALSE, FALSE),
7876 freeAsmop (right, NULL, ic, TRUE);
7877 freeAsmop (result, NULL, ic, TRUE);
7880 /*-----------------------------------------------------------------*/
7881 /* genJumpTab - genrates code for jump table */
7882 /*-----------------------------------------------------------------*/
7884 genJumpTab (iCode * ic)
7889 aopOp (IC_JTCOND (ic), ic, FALSE);
7890 /* get the condition into accumulator */
7891 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7893 /* multiply by three */
7894 emitcode ("add", "a,acc");
7895 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7896 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7898 jtab = newiTempLabel (NULL);
7899 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7900 emitcode ("jmp", "@a+dptr");
7901 emitcode ("", "%05d$:", jtab->key + 100);
7902 /* now generate the jump labels */
7903 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7904 jtab = setNextItem (IC_JTLABELS (ic)))
7905 emitcode ("ljmp", "%05d$", jtab->key + 100);
7909 /*-----------------------------------------------------------------*/
7910 /* genCast - gen code for casting */
7911 /*-----------------------------------------------------------------*/
7913 genCast (iCode * ic)
7915 operand *result = IC_RESULT (ic);
7916 sym_link *ctype = operandType (IC_LEFT (ic));
7917 sym_link *rtype = operandType (IC_RIGHT (ic));
7918 operand *right = IC_RIGHT (ic);
7921 /* if they are equivalent then do nothing */
7922 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7925 aopOp (right, ic, FALSE);
7926 aopOp (result, ic, FALSE);
7928 /* if the result is a bit */
7929 if (AOP_TYPE (result) == AOP_CRY)
7931 /* if the right size is a literal then
7932 we know what the value is */
7933 if (AOP_TYPE (right) == AOP_LIT)
7935 if (((int) operandLitValue (right)))
7936 aopPut (AOP (result), one, 0);
7938 aopPut (AOP (result), zero, 0);
7943 /* the right is also a bit variable */
7944 if (AOP_TYPE (right) == AOP_CRY)
7946 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7947 aopPut (AOP (result), "c", 0);
7953 aopPut (AOP (result), "a", 0);
7957 /* if they are the same size : or less */
7958 if (AOP_SIZE (result) <= AOP_SIZE (right))
7961 /* if they are in the same place */
7962 if (sameRegs (AOP (right), AOP (result)))
7965 /* if they in different places then copy */
7966 size = AOP_SIZE (result);
7970 aopPut (AOP (result),
7971 aopGet (AOP (right), offset, FALSE, FALSE),
7979 /* if the result is of type pointer */
7984 sym_link *type = operandType (right);
7985 sym_link *etype = getSpec (type);
7987 /* pointer to generic pointer */
7988 if (IS_GENPTR (ctype))
7993 p_type = DCL_TYPE (type);
7996 /* we have to go by the storage class */
7997 p_type = PTR_TYPE (SPEC_OCLS (etype));
8000 /* the first two bytes are known */
8001 size = GPTRSIZE - 1;
8005 aopPut (AOP (result),
8006 aopGet (AOP (right), offset, FALSE, FALSE),
8010 /* the last byte depending on type */
8028 /* this should never happen */
8029 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8030 "got unknown pointer type");
8033 aopPut (AOP (result), l, GPTRSIZE - 1);
8037 /* just copy the pointers */
8038 size = AOP_SIZE (result);
8042 aopPut (AOP (result),
8043 aopGet (AOP (right), offset, FALSE, FALSE),
8050 /* so we now know that the size of destination is greater
8051 than the size of the source */
8052 /* we move to result for the size of source */
8053 size = AOP_SIZE (right);
8057 aopPut (AOP (result),
8058 aopGet (AOP (right), offset, FALSE, FALSE),
8063 /* now depending on the sign of the source && destination */
8064 size = AOP_SIZE (result) - AOP_SIZE (right);
8065 /* if unsigned or not an integral type */
8066 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8069 aopPut (AOP (result), zero, offset++);
8073 /* we need to extend the sign :{ */
8074 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8077 emitcode ("rlc", "a");
8078 emitcode ("subb", "a,acc");
8080 aopPut (AOP (result), "a", offset++);
8083 /* we are done hurray !!!! */
8086 freeAsmop (right, NULL, ic, TRUE);
8087 freeAsmop (result, NULL, ic, TRUE);
8091 /*-----------------------------------------------------------------*/
8092 /* genDjnz - generate decrement & jump if not zero instrucion */
8093 /*-----------------------------------------------------------------*/
8095 genDjnz (iCode * ic, iCode * ifx)
8101 /* if the if condition has a false label
8102 then we cannot save */
8106 /* if the minus is not of the form
8108 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8109 !IS_OP_LITERAL (IC_RIGHT (ic)))
8112 if (operandLitValue (IC_RIGHT (ic)) != 1)
8115 /* if the size of this greater than one then no
8117 if (getSize (operandType (IC_RESULT (ic))) > 1)
8120 /* otherwise we can save BIG */
8121 lbl = newiTempLabel (NULL);
8122 lbl1 = newiTempLabel (NULL);
8124 aopOp (IC_RESULT (ic), ic, FALSE);
8126 if (AOP_NEEDSACC(IC_RESULT(ic)))
8128 /* If the result is accessed indirectly via
8129 * the accumulator, we must explicitly write
8130 * it back after the decrement.
8132 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8134 if (strcmp(rByte, "a"))
8136 /* Something is hopelessly wrong */
8137 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8138 __FILE__, __LINE__);
8139 /* We can just give up; the generated code will be inefficient,
8142 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8145 emitcode ("dec", "%s", rByte);
8146 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8147 emitcode ("jnz", "%05d$", lbl->key + 100);
8149 else if (IS_AOP_PREG (IC_RESULT (ic)))
8151 emitcode ("dec", "%s",
8152 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8153 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8154 emitcode ("jnz", "%05d$", lbl->key + 100);
8158 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8161 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8162 emitcode ("", "%05d$:", lbl->key + 100);
8163 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8164 emitcode ("", "%05d$:", lbl1->key + 100);
8166 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genReceive - generate code for a receive iCode */
8173 /*-----------------------------------------------------------------*/
8175 genReceive (iCode * ic)
8177 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8178 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8179 IS_TRUE_SYMOP (IC_RESULT (ic))))
8182 int size = getSize (operandType (IC_RESULT (ic)));
8183 int offset = fReturnSizeMCS51 - size;
8186 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8187 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8190 aopOp (IC_RESULT (ic), ic, FALSE);
8191 size = AOP_SIZE (IC_RESULT (ic));
8195 emitcode ("pop", "acc");
8196 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8203 aopOp (IC_RESULT (ic), ic, FALSE);
8205 assignResultValue (IC_RESULT (ic));
8208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8211 /*-----------------------------------------------------------------*/
8212 /* gen51Code - generate code for 8051 based controllers */
8213 /*-----------------------------------------------------------------*/
8215 gen51Code (iCode * lic)
8220 lineHead = lineCurr = NULL;
8222 /* print the allocation information */
8224 printAllocInfo (currFunc, codeOutFile);
8225 /* if debug information required */
8226 /* if (options.debug && currFunc) { */
8229 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8231 if (IS_STATIC (currFunc->etype))
8232 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8234 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8237 /* stack pointer name */
8238 if (options.useXstack)
8244 for (ic = lic; ic; ic = ic->next)
8247 if (cln != ic->lineno)
8252 emitcode ("", "C$%s$%d$%d$%d ==.",
8253 FileBaseName (ic->filename), ic->lineno,
8254 ic->level, ic->block);
8257 emitcode (";", "%s %d", ic->filename, ic->lineno);
8260 /* if the result is marked as
8261 spilt and rematerializable or code for
8262 this has already been generated then
8264 if (resultRemat (ic) || ic->generated)
8267 /* depending on the operation */
8287 /* IPOP happens only when trying to restore a
8288 spilt live range, if there is an ifx statement
8289 following this pop then the if statement might
8290 be using some of the registers being popped which
8291 would destory the contents of the register so
8292 we need to check for this condition and handle it */
8294 ic->next->op == IFX &&
8295 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8296 genIfx (ic->next, ic);
8314 genEndFunction (ic);
8334 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8351 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8355 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8362 /* note these two are xlated by algebraic equivalence
8363 during parsing SDCC.y */
8364 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8365 "got '>=' or '<=' shouldn't have come here");
8369 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8381 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8385 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8389 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8416 case GET_VALUE_AT_ADDRESS:
8417 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8421 if (POINTER_SET (ic))
8422 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8448 addSet (&_G.sendSet, ic);
8457 /* now we are ready to call the
8458 peep hole optimizer */
8459 if (!options.nopeep)
8460 peepHole (&lineHead);
8462 /* now do the actual printing */
8463 printLine (lineHead, codeOutFile);