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;
4193 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4194 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4195 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4198 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4200 AOP_TYPE (left), AOP_TYPE (right));
4201 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4203 AOP_SIZE (left), AOP_SIZE (right));
4206 /* if left is a literal & right is not then exchange them */
4207 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4208 AOP_NEEDSACC (left))
4210 operand *tmp = right;
4215 /* if result = right then exchange them */
4216 if (sameRegs (AOP (result), AOP (right)))
4218 operand *tmp = right;
4223 /* if right is bit then exchange them */
4224 if (AOP_TYPE (right) == AOP_CRY &&
4225 AOP_TYPE (left) != AOP_CRY)
4227 operand *tmp = right;
4231 if (AOP_TYPE (right) == AOP_LIT)
4232 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4234 size = AOP_SIZE (result);
4237 // result = bit & yy;
4238 if (AOP_TYPE (left) == AOP_CRY)
4240 // c = bit & literal;
4241 if (AOP_TYPE (right) == AOP_LIT)
4245 if (size && sameRegs (AOP (result), AOP (left)))
4248 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4253 if (size && (AOP_TYPE (result) == AOP_CRY))
4255 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4258 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4263 emitcode ("clr", "c");
4268 if (AOP_TYPE (right) == AOP_CRY)
4271 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4272 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4277 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4279 emitcode ("rrc", "a");
4280 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4288 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4289 genIfxJump (ifx, "c");
4293 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4294 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4295 if ((AOP_TYPE (right) == AOP_LIT) &&
4296 (AOP_TYPE (result) == AOP_CRY) &&
4297 (AOP_TYPE (left) != AOP_CRY))
4299 int posbit = isLiteralBit (lit);
4304 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4307 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4313 sprintf (buffer, "acc.%d", posbit & 0x07);
4314 genIfxJump (ifx, buffer);
4321 symbol *tlbl = newiTempLabel (NULL);
4322 int sizel = AOP_SIZE (left);
4324 emitcode ("setb", "c");
4327 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4329 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4331 if ((posbit = isLiteralBit (bytelit)) != 0)
4332 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4335 if (bytelit != 0x0FFL)
4336 emitcode ("anl", "a,%s",
4337 aopGet (AOP (right), offset, FALSE, TRUE));
4338 emitcode ("jnz", "%05d$", tlbl->key + 100);
4343 // bit = left & literal
4346 emitcode ("clr", "c");
4347 emitcode ("", "%05d$:", tlbl->key + 100);
4349 // if(left & literal)
4353 jmpTrueOrFalse (ifx, tlbl);
4361 /* if left is same as result */
4362 if (sameRegs (AOP (result), AOP (left)))
4364 for (; size--; offset++)
4366 if (AOP_TYPE (right) == AOP_LIT)
4368 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4370 else if (bytelit == 0)
4371 aopPut (AOP (result), zero, offset);
4372 else if (IS_AOP_PREG (result))
4374 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4375 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4376 aopPut (AOP (result), "a", offset);
4379 emitcode ("anl", "%s,%s",
4380 aopGet (AOP (left), offset, FALSE, TRUE),
4381 aopGet (AOP (right), offset, FALSE, FALSE));
4385 if (AOP_TYPE (left) == AOP_ACC)
4386 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4389 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4390 if (IS_AOP_PREG (result))
4392 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4393 aopPut (AOP (result), "a", offset);
4397 emitcode ("anl", "%s,a",
4398 aopGet (AOP (left), offset, FALSE, TRUE));
4405 // left & result in different registers
4406 if (AOP_TYPE (result) == AOP_CRY)
4409 // if(size), result in bit
4410 // if(!size && ifx), conditional oper: if(left & right)
4411 symbol *tlbl = newiTempLabel (NULL);
4412 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4414 emitcode ("setb", "c");
4417 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4418 emitcode ("anl", "a,%s",
4419 aopGet (AOP (left), offset, FALSE, FALSE));
4420 emitcode ("jnz", "%05d$", tlbl->key + 100);
4426 emitcode ("", "%05d$:", tlbl->key + 100);
4430 jmpTrueOrFalse (ifx, tlbl);
4434 for (; (size--); offset++)
4437 // result = left & right
4438 if (AOP_TYPE (right) == AOP_LIT)
4440 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4442 aopPut (AOP (result),
4443 aopGet (AOP (left), offset, FALSE, FALSE),
4447 else if (bytelit == 0)
4449 aopPut (AOP (result), zero, offset);
4453 // faster than result <- left, anl result,right
4454 // and better if result is SFR
4455 if (AOP_TYPE (left) == AOP_ACC)
4456 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4459 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4460 emitcode ("anl", "a,%s",
4461 aopGet (AOP (left), offset, FALSE, FALSE));
4463 aopPut (AOP (result), "a", offset);
4469 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (result, NULL, ic, TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* genOr - code for or */
4476 /*-----------------------------------------------------------------*/
4478 genOr (iCode * ic, iCode * ifx)
4480 operand *left, *right, *result;
4481 int size, offset = 0;
4482 unsigned long lit = 0L;
4484 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4485 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4486 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4489 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4491 AOP_TYPE (left), AOP_TYPE (right));
4492 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4494 AOP_SIZE (left), AOP_SIZE (right));
4497 /* if left is a literal & right is not then exchange them */
4498 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4499 AOP_NEEDSACC (left))
4501 operand *tmp = right;
4506 /* if result = right then exchange them */
4507 if (sameRegs (AOP (result), AOP (right)))
4509 operand *tmp = right;
4514 /* if right is bit then exchange them */
4515 if (AOP_TYPE (right) == AOP_CRY &&
4516 AOP_TYPE (left) != AOP_CRY)
4518 operand *tmp = right;
4522 if (AOP_TYPE (right) == AOP_LIT)
4523 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4525 size = AOP_SIZE (result);
4529 if (AOP_TYPE (left) == AOP_CRY)
4531 if (AOP_TYPE (right) == AOP_LIT)
4533 // c = bit & literal;
4536 // lit != 0 => result = 1
4537 if (AOP_TYPE (result) == AOP_CRY)
4540 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4542 continueIfTrue (ifx);
4545 emitcode ("setb", "c");
4549 // lit == 0 => result = left
4550 if (size && sameRegs (AOP (result), AOP (left)))
4552 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4557 if (AOP_TYPE (right) == AOP_CRY)
4560 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4561 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4566 symbol *tlbl = newiTempLabel (NULL);
4567 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4568 emitcode ("setb", "c");
4569 emitcode ("jb", "%s,%05d$",
4570 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4572 emitcode ("jnz", "%05d$", tlbl->key + 100);
4573 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4575 jmpTrueOrFalse (ifx, tlbl);
4581 emitcode ("", "%05d$:", tlbl->key + 100);
4590 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4591 genIfxJump (ifx, "c");
4595 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4596 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4597 if ((AOP_TYPE (right) == AOP_LIT) &&
4598 (AOP_TYPE (result) == AOP_CRY) &&
4599 (AOP_TYPE (left) != AOP_CRY))
4605 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4607 continueIfTrue (ifx);
4612 // lit = 0, result = boolean(left)
4614 emitcode ("setb", "c");
4618 symbol *tlbl = newiTempLabel (NULL);
4619 emitcode ("jnz", "%05d$", tlbl->key + 100);
4621 emitcode ("", "%05d$:", tlbl->key + 100);
4625 genIfxJump (ifx, "a");
4633 /* if left is same as result */
4634 if (sameRegs (AOP (result), AOP (left)))
4636 for (; size--; offset++)
4638 if (AOP_TYPE (right) == AOP_LIT)
4640 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4642 else if (IS_AOP_PREG (left))
4644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4645 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4646 aopPut (AOP (result), "a", offset);
4649 emitcode ("orl", "%s,%s",
4650 aopGet (AOP (left), offset, FALSE, TRUE),
4651 aopGet (AOP (right), offset, FALSE, FALSE));
4655 if (AOP_TYPE (left) == AOP_ACC)
4656 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4659 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4660 if (IS_AOP_PREG (left))
4662 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4663 aopPut (AOP (result), "a", offset);
4666 emitcode ("orl", "%s,a",
4667 aopGet (AOP (left), offset, FALSE, TRUE));
4674 // left & result in different registers
4675 if (AOP_TYPE (result) == AOP_CRY)
4678 // if(size), result in bit
4679 // if(!size && ifx), conditional oper: if(left | right)
4680 symbol *tlbl = newiTempLabel (NULL);
4681 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4683 emitcode ("setb", "c");
4686 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4687 emitcode ("orl", "a,%s",
4688 aopGet (AOP (left), offset, FALSE, FALSE));
4689 emitcode ("jnz", "%05d$", tlbl->key + 100);
4695 emitcode ("", "%05d$:", tlbl->key + 100);
4699 jmpTrueOrFalse (ifx, tlbl);
4702 for (; (size--); offset++)
4705 // result = left & right
4706 if (AOP_TYPE (right) == AOP_LIT)
4708 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4710 aopPut (AOP (result),
4711 aopGet (AOP (left), offset, FALSE, FALSE),
4716 // faster than result <- left, anl result,right
4717 // and better if result is SFR
4718 if (AOP_TYPE (left) == AOP_ACC)
4719 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4722 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4723 emitcode ("orl", "a,%s",
4724 aopGet (AOP (left), offset, FALSE, FALSE));
4726 aopPut (AOP (result), "a", offset);
4731 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4732 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4733 freeAsmop (result, NULL, ic, TRUE);
4736 /*-----------------------------------------------------------------*/
4737 /* genXor - code for xclusive or */
4738 /*-----------------------------------------------------------------*/
4740 genXor (iCode * ic, iCode * ifx)
4742 operand *left, *right, *result;
4743 int size, offset = 0;
4744 unsigned long lit = 0L;
4746 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4747 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4748 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4751 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4753 AOP_TYPE (left), AOP_TYPE (right));
4754 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4756 AOP_SIZE (left), AOP_SIZE (right));
4759 /* if left is a literal & right is not ||
4760 if left needs acc & right does not */
4761 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4762 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4764 operand *tmp = right;
4769 /* if result = right then exchange them */
4770 if (sameRegs (AOP (result), AOP (right)))
4772 operand *tmp = right;
4777 /* if right is bit then exchange them */
4778 if (AOP_TYPE (right) == AOP_CRY &&
4779 AOP_TYPE (left) != AOP_CRY)
4781 operand *tmp = right;
4785 if (AOP_TYPE (right) == AOP_LIT)
4786 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4788 size = AOP_SIZE (result);
4792 if (AOP_TYPE (left) == AOP_CRY)
4794 if (AOP_TYPE (right) == AOP_LIT)
4796 // c = bit & literal;
4799 // lit>>1 != 0 => result = 1
4800 if (AOP_TYPE (result) == AOP_CRY)
4803 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4805 continueIfTrue (ifx);
4808 emitcode ("setb", "c");
4815 // lit == 0, result = left
4816 if (size && sameRegs (AOP (result), AOP (left)))
4818 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4822 // lit == 1, result = not(left)
4823 if (size && sameRegs (AOP (result), AOP (left)))
4825 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4831 emitcode ("cpl", "c");
4840 symbol *tlbl = newiTempLabel (NULL);
4841 if (AOP_TYPE (right) == AOP_CRY)
4844 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4848 int sizer = AOP_SIZE (right);
4850 // if val>>1 != 0, result = 1
4851 emitcode ("setb", "c");
4854 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4856 // test the msb of the lsb
4857 emitcode ("anl", "a,#0xfe");
4858 emitcode ("jnz", "%05d$", tlbl->key + 100);
4862 emitcode ("rrc", "a");
4864 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4865 emitcode ("cpl", "c");
4866 emitcode ("", "%05d$:", (tlbl->key + 100));
4873 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4874 genIfxJump (ifx, "c");
4878 if (sameRegs (AOP (result), AOP (left)))
4880 /* if left is same as result */
4881 for (; size--; offset++)
4883 if (AOP_TYPE (right) == AOP_LIT)
4885 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4887 else if (IS_AOP_PREG (left))
4889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4890 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4891 aopPut (AOP (result), "a", offset);
4894 emitcode ("xrl", "%s,%s",
4895 aopGet (AOP (left), offset, FALSE, TRUE),
4896 aopGet (AOP (right), offset, FALSE, FALSE));
4900 if (AOP_TYPE (left) == AOP_ACC)
4901 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4905 if (IS_AOP_PREG (left))
4907 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4908 aopPut (AOP (result), "a", offset);
4911 emitcode ("xrl", "%s,a",
4912 aopGet (AOP (left), offset, FALSE, TRUE));
4919 // left & result in different registers
4920 if (AOP_TYPE (result) == AOP_CRY)
4923 // if(size), result in bit
4924 // if(!size && ifx), conditional oper: if(left ^ right)
4925 symbol *tlbl = newiTempLabel (NULL);
4926 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4928 emitcode ("setb", "c");
4931 if ((AOP_TYPE (right) == AOP_LIT) &&
4932 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4934 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4938 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4939 emitcode ("xrl", "a,%s",
4940 aopGet (AOP (left), offset, FALSE, FALSE));
4942 emitcode ("jnz", "%05d$", tlbl->key + 100);
4948 emitcode ("", "%05d$:", tlbl->key + 100);
4952 jmpTrueOrFalse (ifx, tlbl);
4955 for (; (size--); offset++)
4958 // result = left & right
4959 if (AOP_TYPE (right) == AOP_LIT)
4961 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4963 aopPut (AOP (result),
4964 aopGet (AOP (left), offset, FALSE, FALSE),
4969 // faster than result <- left, anl result,right
4970 // and better if result is SFR
4971 if (AOP_TYPE (left) == AOP_ACC)
4972 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4976 emitcode ("xrl", "a,%s",
4977 aopGet (AOP (left), offset, FALSE, TRUE));
4979 aopPut (AOP (result), "a", offset);
4984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986 freeAsmop (result, NULL, ic, TRUE);
4989 /*-----------------------------------------------------------------*/
4990 /* genInline - write the inline code out */
4991 /*-----------------------------------------------------------------*/
4993 genInline (iCode * ic)
4995 char buffer[MAX_INLINEASM];
4999 _G.inLine += (!options.asmpeep);
5000 strcpy (buffer, IC_INLINE (ic));
5002 /* emit each line as a code */
5027 /* emitcode("",buffer); */
5028 _G.inLine -= (!options.asmpeep);
5031 /*-----------------------------------------------------------------*/
5032 /* genRRC - rotate right with carry */
5033 /*-----------------------------------------------------------------*/
5037 operand *left, *result;
5038 int size, offset = 0;
5041 /* rotate right with carry */
5042 left = IC_LEFT (ic);
5043 result = IC_RESULT (ic);
5044 aopOp (left, ic, FALSE);
5045 aopOp (result, ic, FALSE);
5047 /* move it to the result */
5048 size = AOP_SIZE (result);
5053 l = aopGet (AOP (left), offset, FALSE, FALSE);
5055 emitcode ("rrc", "a");
5056 if (AOP_SIZE (result) > 1)
5057 aopPut (AOP (result), "a", offset--);
5059 /* now we need to put the carry into the
5060 highest order byte of the result */
5061 if (AOP_SIZE (result) > 1)
5063 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5066 emitcode ("mov", "acc.7,c");
5067 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5068 freeAsmop (left, NULL, ic, TRUE);
5069 freeAsmop (result, NULL, ic, TRUE);
5072 /*-----------------------------------------------------------------*/
5073 /* genRLC - generate code for rotate left with carry */
5074 /*-----------------------------------------------------------------*/
5078 operand *left, *result;
5079 int size, offset = 0;
5082 /* rotate right with carry */
5083 left = IC_LEFT (ic);
5084 result = IC_RESULT (ic);
5085 aopOp (left, ic, FALSE);
5086 aopOp (result, ic, FALSE);
5088 /* move it to the result */
5089 size = AOP_SIZE (result);
5093 l = aopGet (AOP (left), offset, FALSE, FALSE);
5095 emitcode ("add", "a,acc");
5096 if (AOP_SIZE (result) > 1)
5097 aopPut (AOP (result), "a", offset++);
5100 l = aopGet (AOP (left), offset, FALSE, FALSE);
5102 emitcode ("rlc", "a");
5103 if (AOP_SIZE (result) > 1)
5104 aopPut (AOP (result), "a", offset++);
5107 /* now we need to put the carry into the
5108 highest order byte of the result */
5109 if (AOP_SIZE (result) > 1)
5111 l = aopGet (AOP (result), 0, FALSE, FALSE);
5114 emitcode ("mov", "acc.0,c");
5115 aopPut (AOP (result), "a", 0);
5116 freeAsmop (left, NULL, ic, TRUE);
5117 freeAsmop (result, NULL, ic, TRUE);
5120 /*-----------------------------------------------------------------*/
5121 /* genGetHbit - generates code get highest order bit */
5122 /*-----------------------------------------------------------------*/
5124 genGetHbit (iCode * ic)
5126 operand *left, *result;
5127 left = IC_LEFT (ic);
5128 result = IC_RESULT (ic);
5129 aopOp (left, ic, FALSE);
5130 aopOp (result, ic, FALSE);
5132 /* get the highest order byte into a */
5133 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5134 if (AOP_TYPE (result) == AOP_CRY)
5136 emitcode ("rlc", "a");
5141 emitcode ("rl", "a");
5142 emitcode ("anl", "a,#0x01");
5147 freeAsmop (left, NULL, ic, TRUE);
5148 freeAsmop (result, NULL, ic, TRUE);
5151 /*-----------------------------------------------------------------*/
5152 /* AccRol - rotate left accumulator by known count */
5153 /*-----------------------------------------------------------------*/
5155 AccRol (int shCount)
5157 shCount &= 0x0007; // shCount : 0..7
5164 emitcode ("rl", "a");
5167 emitcode ("rl", "a");
5168 emitcode ("rl", "a");
5171 emitcode ("swap", "a");
5172 emitcode ("rr", "a");
5175 emitcode ("swap", "a");
5178 emitcode ("swap", "a");
5179 emitcode ("rl", "a");
5182 emitcode ("rr", "a");
5183 emitcode ("rr", "a");
5186 emitcode ("rr", "a");
5191 /*-----------------------------------------------------------------*/
5192 /* AccLsh - left shift accumulator by known count */
5193 /*-----------------------------------------------------------------*/
5195 AccLsh (int shCount)
5200 emitcode ("add", "a,acc");
5201 else if (shCount == 2)
5203 emitcode ("add", "a,acc");
5204 emitcode ("add", "a,acc");
5208 /* rotate left accumulator */
5210 /* and kill the lower order bits */
5211 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5216 /*-----------------------------------------------------------------*/
5217 /* AccRsh - right shift accumulator by known count */
5218 /*-----------------------------------------------------------------*/
5220 AccRsh (int shCount)
5227 emitcode ("rrc", "a");
5231 /* rotate right accumulator */
5232 AccRol (8 - shCount);
5233 /* and kill the higher order bits */
5234 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5239 /*-----------------------------------------------------------------*/
5240 /* AccSRsh - signed right shift accumulator by known count */
5241 /*-----------------------------------------------------------------*/
5243 AccSRsh (int shCount)
5250 emitcode ("mov", "c,acc.7");
5251 emitcode ("rrc", "a");
5253 else if (shCount == 2)
5255 emitcode ("mov", "c,acc.7");
5256 emitcode ("rrc", "a");
5257 emitcode ("mov", "c,acc.7");
5258 emitcode ("rrc", "a");
5262 tlbl = newiTempLabel (NULL);
5263 /* rotate right accumulator */
5264 AccRol (8 - shCount);
5265 /* and kill the higher order bits */
5266 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5267 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5268 emitcode ("orl", "a,#0x%02x",
5269 (unsigned char) ~SRMask[shCount]);
5270 emitcode ("", "%05d$:", tlbl->key + 100);
5275 /*-----------------------------------------------------------------*/
5276 /* shiftR1Left2Result - shift right one byte from left to result */
5277 /*-----------------------------------------------------------------*/
5279 shiftR1Left2Result (operand * left, int offl,
5280 operand * result, int offr,
5281 int shCount, int sign)
5283 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5284 /* shift right accumulator */
5289 aopPut (AOP (result), "a", offr);
5292 /*-----------------------------------------------------------------*/
5293 /* shiftL1Left2Result - shift left one byte from left to result */
5294 /*-----------------------------------------------------------------*/
5296 shiftL1Left2Result (operand * left, int offl,
5297 operand * result, int offr, int shCount)
5300 l = aopGet (AOP (left), offl, FALSE, FALSE);
5302 /* shift left accumulator */
5304 aopPut (AOP (result), "a", offr);
5307 /*-----------------------------------------------------------------*/
5308 /* movLeft2Result - move byte from left to result */
5309 /*-----------------------------------------------------------------*/
5311 movLeft2Result (operand * left, int offl,
5312 operand * result, int offr, int sign)
5315 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5317 l = aopGet (AOP (left), offl, FALSE, FALSE);
5319 if (*l == '@' && (IS_AOP_PREG (result)))
5321 emitcode ("mov", "a,%s", l);
5322 aopPut (AOP (result), "a", offr);
5327 aopPut (AOP (result), l, offr);
5330 /* MSB sign in acc.7 ! */
5331 if (getDataSize (left) == offl + 1)
5333 emitcode ("mov", "a,%s", l);
5334 aopPut (AOP (result), "a", offr);
5341 /*-----------------------------------------------------------------*/
5342 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5343 /*-----------------------------------------------------------------*/
5347 emitcode ("rrc", "a");
5348 emitcode ("xch", "a,%s", x);
5349 emitcode ("rrc", "a");
5350 emitcode ("xch", "a,%s", x);
5353 /*-----------------------------------------------------------------*/
5354 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5355 /*-----------------------------------------------------------------*/
5359 emitcode ("xch", "a,%s", x);
5360 emitcode ("rlc", "a");
5361 emitcode ("xch", "a,%s", x);
5362 emitcode ("rlc", "a");
5365 /*-----------------------------------------------------------------*/
5366 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5367 /*-----------------------------------------------------------------*/
5371 emitcode ("xch", "a,%s", x);
5372 emitcode ("add", "a,acc");
5373 emitcode ("xch", "a,%s", x);
5374 emitcode ("rlc", "a");
5377 /*-----------------------------------------------------------------*/
5378 /* AccAXLsh - left shift a:x by known count (0..7) */
5379 /*-----------------------------------------------------------------*/
5381 AccAXLsh (char *x, int shCount)
5396 case 5: // AAAAABBB:CCCCCDDD
5398 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5400 emitcode ("anl", "a,#0x%02x",
5401 SLMask[shCount]); // BBB00000:CCCCCDDD
5403 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5405 AccRol (shCount); // DDDCCCCC:BBB00000
5407 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5409 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5411 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5413 emitcode ("anl", "a,#0x%02x",
5414 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5416 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5418 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5421 case 6: // AAAAAABB:CCCCCCDD
5422 emitcode ("anl", "a,#0x%02x",
5423 SRMask[shCount]); // 000000BB:CCCCCCDD
5424 emitcode ("mov", "c,acc.0"); // c = B
5425 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5427 AccAXRrl1 (x); // BCCCCCCD:D000000B
5428 AccAXRrl1 (x); // BBCCCCCC:DD000000
5430 emitcode("rrc","a");
5431 emitcode("xch","a,%s", x);
5432 emitcode("rrc","a");
5433 emitcode("mov","c,acc.0"); //<< get correct bit
5434 emitcode("xch","a,%s", x);
5436 emitcode("rrc","a");
5437 emitcode("xch","a,%s", x);
5438 emitcode("rrc","a");
5439 emitcode("xch","a,%s", x);
5442 case 7: // a:x <<= 7
5444 emitcode ("anl", "a,#0x%02x",
5445 SRMask[shCount]); // 0000000B:CCCCCCCD
5447 emitcode ("mov", "c,acc.0"); // c = B
5449 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5451 AccAXRrl1 (x); // BCCCCCCC:D0000000
5459 /*-----------------------------------------------------------------*/
5460 /* AccAXRsh - right shift a:x known count (0..7) */
5461 /*-----------------------------------------------------------------*/
5463 AccAXRsh (char *x, int shCount)
5471 AccAXRrl1 (x); // 0->a:x
5476 AccAXRrl1 (x); // 0->a:x
5479 AccAXRrl1 (x); // 0->a:x
5484 case 5: // AAAAABBB:CCCCCDDD = a:x
5486 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5488 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5490 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5492 emitcode ("anl", "a,#0x%02x",
5493 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5495 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5497 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5499 emitcode ("anl", "a,#0x%02x",
5500 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5502 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5504 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5506 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5509 case 6: // AABBBBBB:CCDDDDDD
5511 emitcode ("mov", "c,acc.7");
5512 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5514 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5516 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5518 emitcode ("anl", "a,#0x%02x",
5519 SRMask[shCount]); // 000000AA:BBBBBBCC
5522 case 7: // ABBBBBBB:CDDDDDDD
5524 emitcode ("mov", "c,acc.7"); // c = A
5526 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5528 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5530 emitcode ("anl", "a,#0x%02x",
5531 SRMask[shCount]); // 0000000A:BBBBBBBC
5539 /*-----------------------------------------------------------------*/
5540 /* AccAXRshS - right shift signed a:x known count (0..7) */
5541 /*-----------------------------------------------------------------*/
5543 AccAXRshS (char *x, int shCount)
5551 emitcode ("mov", "c,acc.7");
5552 AccAXRrl1 (x); // s->a:x
5556 emitcode ("mov", "c,acc.7");
5557 AccAXRrl1 (x); // s->a:x
5559 emitcode ("mov", "c,acc.7");
5560 AccAXRrl1 (x); // s->a:x
5565 case 5: // AAAAABBB:CCCCCDDD = a:x
5567 tlbl = newiTempLabel (NULL);
5568 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5570 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5572 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5574 emitcode ("anl", "a,#0x%02x",
5575 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5577 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5579 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5581 emitcode ("anl", "a,#0x%02x",
5582 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5584 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5586 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5588 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5590 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5591 emitcode ("orl", "a,#0x%02x",
5592 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5594 emitcode ("", "%05d$:", tlbl->key + 100);
5595 break; // SSSSAAAA:BBBCCCCC
5597 case 6: // AABBBBBB:CCDDDDDD
5599 tlbl = newiTempLabel (NULL);
5600 emitcode ("mov", "c,acc.7");
5601 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5603 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5605 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5607 emitcode ("anl", "a,#0x%02x",
5608 SRMask[shCount]); // 000000AA:BBBBBBCC
5610 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5611 emitcode ("orl", "a,#0x%02x",
5612 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5614 emitcode ("", "%05d$:", tlbl->key + 100);
5616 case 7: // ABBBBBBB:CDDDDDDD
5618 tlbl = newiTempLabel (NULL);
5619 emitcode ("mov", "c,acc.7"); // c = A
5621 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5623 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5625 emitcode ("anl", "a,#0x%02x",
5626 SRMask[shCount]); // 0000000A:BBBBBBBC
5628 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5629 emitcode ("orl", "a,#0x%02x",
5630 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5632 emitcode ("", "%05d$:", tlbl->key + 100);
5639 /*-----------------------------------------------------------------*/
5640 /* shiftL2Left2Result - shift left two bytes from left to result */
5641 /*-----------------------------------------------------------------*/
5643 shiftL2Left2Result (operand * left, int offl,
5644 operand * result, int offr, int shCount)
5646 if (sameRegs (AOP (result), AOP (left)) &&
5647 ((offl + MSB16) == offr))
5649 /* don't crash result[offr] */
5650 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5651 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5655 movLeft2Result (left, offl, result, offr, 0);
5656 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5658 /* ax << shCount (x = lsb(result)) */
5659 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5660 aopPut (AOP (result), "a", offr + MSB16);
5664 /*-----------------------------------------------------------------*/
5665 /* shiftR2Left2Result - shift right two bytes from left to result */
5666 /*-----------------------------------------------------------------*/
5668 shiftR2Left2Result (operand * left, int offl,
5669 operand * result, int offr,
5670 int shCount, int sign)
5672 if (sameRegs (AOP (result), AOP (left)) &&
5673 ((offl + MSB16) == offr))
5675 /* don't crash result[offr] */
5676 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5677 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5681 movLeft2Result (left, offl, result, offr, 0);
5682 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5684 /* a:x >> shCount (x = lsb(result)) */
5686 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5688 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5689 if (getDataSize (result) > 1)
5690 aopPut (AOP (result), "a", offr + MSB16);
5693 /*-----------------------------------------------------------------*/
5694 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5695 /*-----------------------------------------------------------------*/
5697 shiftLLeftOrResult (operand * left, int offl,
5698 operand * result, int offr, int shCount)
5700 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5701 /* shift left accumulator */
5703 /* or with result */
5704 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5705 /* back to result */
5706 aopPut (AOP (result), "a", offr);
5709 /*-----------------------------------------------------------------*/
5710 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5711 /*-----------------------------------------------------------------*/
5713 shiftRLeftOrResult (operand * left, int offl,
5714 operand * result, int offr, int shCount)
5716 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5717 /* shift right accumulator */
5719 /* or with result */
5720 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5721 /* back to result */
5722 aopPut (AOP (result), "a", offr);
5725 /*-----------------------------------------------------------------*/
5726 /* genlshOne - left shift a one byte quantity by known count */
5727 /*-----------------------------------------------------------------*/
5729 genlshOne (operand * result, operand * left, int shCount)
5731 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5734 /*-----------------------------------------------------------------*/
5735 /* genlshTwo - left shift two bytes by known amount != 0 */
5736 /*-----------------------------------------------------------------*/
5738 genlshTwo (operand * result, operand * left, int shCount)
5742 size = getDataSize (result);
5744 /* if shCount >= 8 */
5752 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5754 movLeft2Result (left, LSB, result, MSB16, 0);
5756 aopPut (AOP (result), zero, LSB);
5759 /* 1 <= shCount <= 7 */
5763 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5765 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5769 /*-----------------------------------------------------------------*/
5770 /* shiftLLong - shift left one long from left to result */
5771 /* offl = LSB or MSB16 */
5772 /*-----------------------------------------------------------------*/
5774 shiftLLong (operand * left, operand * result, int offr)
5777 int size = AOP_SIZE (result);
5779 if (size >= LSB + offr)
5781 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5783 emitcode ("add", "a,acc");
5784 if (sameRegs (AOP (left), AOP (result)) &&
5785 size >= MSB16 + offr && offr != LSB)
5786 emitcode ("xch", "a,%s",
5787 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5789 aopPut (AOP (result), "a", LSB + offr);
5792 if (size >= MSB16 + offr)
5794 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5796 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5799 emitcode ("rlc", "a");
5800 if (sameRegs (AOP (left), AOP (result)) &&
5801 size >= MSB24 + offr && offr != LSB)
5802 emitcode ("xch", "a,%s",
5803 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5805 aopPut (AOP (result), "a", MSB16 + offr);
5808 if (size >= MSB24 + offr)
5810 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5812 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5815 emitcode ("rlc", "a");
5816 if (sameRegs (AOP (left), AOP (result)) &&
5817 size >= MSB32 + offr && offr != LSB)
5818 emitcode ("xch", "a,%s",
5819 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5821 aopPut (AOP (result), "a", MSB24 + offr);
5824 if (size > MSB32 + offr)
5826 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5828 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5831 emitcode ("rlc", "a");
5832 aopPut (AOP (result), "a", MSB32 + offr);
5835 aopPut (AOP (result), zero, LSB);
5838 /*-----------------------------------------------------------------*/
5839 /* genlshFour - shift four byte by a known amount != 0 */
5840 /*-----------------------------------------------------------------*/
5842 genlshFour (operand * result, operand * left, int shCount)
5846 size = AOP_SIZE (result);
5848 /* if shifting more that 3 bytes */
5853 /* lowest order of left goes to the highest
5854 order of the destination */
5855 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5857 movLeft2Result (left, LSB, result, MSB32, 0);
5858 aopPut (AOP (result), zero, LSB);
5859 aopPut (AOP (result), zero, MSB16);
5860 aopPut (AOP (result), zero, MSB24);
5864 /* more than two bytes */
5865 else if (shCount >= 16)
5867 /* lower order two bytes goes to higher order two bytes */
5869 /* if some more remaining */
5871 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5874 movLeft2Result (left, MSB16, result, MSB32, 0);
5875 movLeft2Result (left, LSB, result, MSB24, 0);
5877 aopPut (AOP (result), zero, MSB16);
5878 aopPut (AOP (result), zero, LSB);
5882 /* if more than 1 byte */
5883 else if (shCount >= 8)
5885 /* lower order three bytes goes to higher order three bytes */
5890 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5892 movLeft2Result (left, LSB, result, MSB16, 0);
5898 movLeft2Result (left, MSB24, result, MSB32, 0);
5899 movLeft2Result (left, MSB16, result, MSB24, 0);
5900 movLeft2Result (left, LSB, result, MSB16, 0);
5901 aopPut (AOP (result), zero, LSB);
5903 else if (shCount == 1)
5904 shiftLLong (left, result, MSB16);
5907 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5908 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5909 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5910 aopPut (AOP (result), zero, LSB);
5915 /* 1 <= shCount <= 7 */
5916 else if (shCount <= 2)
5918 shiftLLong (left, result, LSB);
5920 shiftLLong (result, result, LSB);
5922 /* 3 <= shCount <= 7, optimize */
5925 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5926 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5927 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5931 /*-----------------------------------------------------------------*/
5932 /* genLeftShiftLiteral - left shifting by known count */
5933 /*-----------------------------------------------------------------*/
5935 genLeftShiftLiteral (operand * left,
5940 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5943 freeAsmop (right, NULL, ic, TRUE);
5945 aopOp (left, ic, FALSE);
5946 aopOp (result, ic, FALSE);
5948 size = getSize (operandType (result));
5951 emitcode ("; shift left ", "result %d, left %d", size,
5955 /* I suppose that the left size >= result size */
5960 movLeft2Result (left, size, result, size, 0);
5964 else if (shCount >= (size * 8))
5966 aopPut (AOP (result), zero, size);
5972 genlshOne (result, left, shCount);
5977 genlshTwo (result, left, shCount);
5981 genlshFour (result, left, shCount);
5985 freeAsmop (left, NULL, ic, TRUE);
5986 freeAsmop (result, NULL, ic, TRUE);
5989 /*-----------------------------------------------------------------*/
5990 /* genLeftShift - generates code for left shifting */
5991 /*-----------------------------------------------------------------*/
5993 genLeftShift (iCode * ic)
5995 operand *left, *right, *result;
5998 symbol *tlbl, *tlbl1;
6000 right = IC_RIGHT (ic);
6001 left = IC_LEFT (ic);
6002 result = IC_RESULT (ic);
6004 aopOp (right, ic, FALSE);
6006 /* if the shift count is known then do it
6007 as efficiently as possible */
6008 if (AOP_TYPE (right) == AOP_LIT)
6010 genLeftShiftLiteral (left, right, result, ic);
6014 /* shift count is unknown then we have to form
6015 a loop get the loop count in B : Note: we take
6016 only the lower order byte since shifting
6017 more that 32 bits make no sense anyway, ( the
6018 largest size of an object can be only 32 bits ) */
6020 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6021 emitcode ("inc", "b");
6022 freeAsmop (right, NULL, ic, TRUE);
6023 aopOp (left, ic, FALSE);
6024 aopOp (result, ic, FALSE);
6026 /* now move the left to the result if they are not the
6028 if (!sameRegs (AOP (left), AOP (result)) &&
6029 AOP_SIZE (result) > 1)
6032 size = AOP_SIZE (result);
6036 l = aopGet (AOP (left), offset, FALSE, TRUE);
6037 if (*l == '@' && (IS_AOP_PREG (result)))
6040 emitcode ("mov", "a,%s", l);
6041 aopPut (AOP (result), "a", offset);
6044 aopPut (AOP (result), l, offset);
6049 tlbl = newiTempLabel (NULL);
6050 size = AOP_SIZE (result);
6052 tlbl1 = newiTempLabel (NULL);
6054 /* if it is only one byte then */
6057 symbol *tlbl1 = newiTempLabel (NULL);
6059 l = aopGet (AOP (left), 0, FALSE, FALSE);
6061 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6062 emitcode ("", "%05d$:", tlbl->key + 100);
6063 emitcode ("add", "a,acc");
6064 emitcode ("", "%05d$:", tlbl1->key + 100);
6065 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6066 aopPut (AOP (result), "a", 0);
6070 reAdjustPreg (AOP (result));
6072 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6073 emitcode ("", "%05d$:", tlbl->key + 100);
6074 l = aopGet (AOP (result), offset, FALSE, FALSE);
6076 emitcode ("add", "a,acc");
6077 aopPut (AOP (result), "a", offset++);
6080 l = aopGet (AOP (result), offset, FALSE, FALSE);
6082 emitcode ("rlc", "a");
6083 aopPut (AOP (result), "a", offset++);
6085 reAdjustPreg (AOP (result));
6087 emitcode ("", "%05d$:", tlbl1->key + 100);
6088 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6090 freeAsmop (left, NULL, ic, TRUE);
6091 freeAsmop (result, NULL, ic, TRUE);
6094 /*-----------------------------------------------------------------*/
6095 /* genrshOne - right shift a one byte quantity by known count */
6096 /*-----------------------------------------------------------------*/
6098 genrshOne (operand * result, operand * left,
6099 int shCount, int sign)
6101 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6104 /*-----------------------------------------------------------------*/
6105 /* genrshTwo - right shift two bytes by known amount != 0 */
6106 /*-----------------------------------------------------------------*/
6108 genrshTwo (operand * result, operand * left,
6109 int shCount, int sign)
6111 /* if shCount >= 8 */
6116 shiftR1Left2Result (left, MSB16, result, LSB,
6119 movLeft2Result (left, MSB16, result, LSB, sign);
6120 addSign (result, MSB16, sign);
6123 /* 1 <= shCount <= 7 */
6125 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6128 /*-----------------------------------------------------------------*/
6129 /* shiftRLong - shift right one long from left to result */
6130 /* offl = LSB or MSB16 */
6131 /*-----------------------------------------------------------------*/
6133 shiftRLong (operand * left, int offl,
6134 operand * result, int sign)
6137 emitcode ("clr", "c");
6138 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6140 emitcode ("mov", "c,acc.7");
6141 emitcode ("rrc", "a");
6142 aopPut (AOP (result), "a", MSB32 - offl);
6144 /* add sign of "a" */
6145 addSign (result, MSB32, sign);
6147 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6148 emitcode ("rrc", "a");
6149 aopPut (AOP (result), "a", MSB24 - offl);
6151 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6152 emitcode ("rrc", "a");
6153 aopPut (AOP (result), "a", MSB16 - offl);
6157 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6158 emitcode ("rrc", "a");
6159 aopPut (AOP (result), "a", LSB);
6163 /*-----------------------------------------------------------------*/
6164 /* genrshFour - shift four byte by a known amount != 0 */
6165 /*-----------------------------------------------------------------*/
6167 genrshFour (operand * result, operand * left,
6168 int shCount, int sign)
6170 /* if shifting more that 3 bytes */
6175 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6177 movLeft2Result (left, MSB32, result, LSB, sign);
6178 addSign (result, MSB16, sign);
6180 else if (shCount >= 16)
6184 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6187 movLeft2Result (left, MSB24, result, LSB, 0);
6188 movLeft2Result (left, MSB32, result, MSB16, sign);
6190 addSign (result, MSB24, sign);
6192 else if (shCount >= 8)
6196 shiftRLong (left, MSB16, result, sign);
6197 else if (shCount == 0)
6199 movLeft2Result (left, MSB16, result, LSB, 0);
6200 movLeft2Result (left, MSB24, result, MSB16, 0);
6201 movLeft2Result (left, MSB32, result, MSB24, sign);
6202 addSign (result, MSB32, sign);
6206 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6207 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6208 /* the last shift is signed */
6209 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6210 addSign (result, MSB32, sign);
6214 { /* 1 <= shCount <= 7 */
6217 shiftRLong (left, LSB, result, sign);
6219 shiftRLong (result, LSB, result, sign);
6223 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6224 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6225 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6230 /*-----------------------------------------------------------------*/
6231 /* genRightShiftLiteral - right shifting by known count */
6232 /*-----------------------------------------------------------------*/
6234 genRightShiftLiteral (operand * left,
6240 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6243 freeAsmop (right, NULL, ic, TRUE);
6245 aopOp (left, ic, FALSE);
6246 aopOp (result, ic, FALSE);
6249 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6253 size = getDataSize (left);
6254 /* test the LEFT size !!! */
6256 /* I suppose that the left size >= result size */
6259 size = getDataSize (result);
6261 movLeft2Result (left, size, result, size, 0);
6264 else if (shCount >= (size * 8))
6267 /* get sign in acc.7 */
6268 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6269 addSign (result, LSB, sign);
6276 genrshOne (result, left, shCount, sign);
6280 genrshTwo (result, left, shCount, sign);
6284 genrshFour (result, left, shCount, sign);
6290 freeAsmop (left, NULL, ic, TRUE);
6291 freeAsmop (result, NULL, ic, TRUE);
6295 /*-----------------------------------------------------------------*/
6296 /* genSignedRightShift - right shift of signed number */
6297 /*-----------------------------------------------------------------*/
6299 genSignedRightShift (iCode * ic)
6301 operand *right, *left, *result;
6304 symbol *tlbl, *tlbl1;
6306 /* we do it the hard way put the shift count in b
6307 and loop thru preserving the sign */
6309 right = IC_RIGHT (ic);
6310 left = IC_LEFT (ic);
6311 result = IC_RESULT (ic);
6313 aopOp (right, ic, FALSE);
6316 if (AOP_TYPE (right) == AOP_LIT)
6318 genRightShiftLiteral (left, right, result, ic, 1);
6321 /* shift count is unknown then we have to form
6322 a loop get the loop count in B : Note: we take
6323 only the lower order byte since shifting
6324 more that 32 bits make no sense anyway, ( the
6325 largest size of an object can be only 32 bits ) */
6327 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6328 emitcode ("inc", "b");
6329 freeAsmop (right, NULL, ic, TRUE);
6330 aopOp (left, ic, FALSE);
6331 aopOp (result, ic, FALSE);
6333 /* now move the left to the result if they are not the
6335 if (!sameRegs (AOP (left), AOP (result)) &&
6336 AOP_SIZE (result) > 1)
6339 size = AOP_SIZE (result);
6343 l = aopGet (AOP (left), offset, FALSE, TRUE);
6344 if (*l == '@' && IS_AOP_PREG (result))
6347 emitcode ("mov", "a,%s", l);
6348 aopPut (AOP (result), "a", offset);
6351 aopPut (AOP (result), l, offset);
6356 /* mov the highest order bit to OVR */
6357 tlbl = newiTempLabel (NULL);
6358 tlbl1 = newiTempLabel (NULL);
6360 size = AOP_SIZE (result);
6362 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6363 emitcode ("rlc", "a");
6364 emitcode ("mov", "ov,c");
6365 /* if it is only one byte then */
6368 l = aopGet (AOP (left), 0, FALSE, FALSE);
6370 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6371 emitcode ("", "%05d$:", tlbl->key + 100);
6372 emitcode ("mov", "c,ov");
6373 emitcode ("rrc", "a");
6374 emitcode ("", "%05d$:", tlbl1->key + 100);
6375 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6376 aopPut (AOP (result), "a", 0);
6380 reAdjustPreg (AOP (result));
6381 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6382 emitcode ("", "%05d$:", tlbl->key + 100);
6383 emitcode ("mov", "c,ov");
6386 l = aopGet (AOP (result), offset, FALSE, FALSE);
6388 emitcode ("rrc", "a");
6389 aopPut (AOP (result), "a", offset--);
6391 reAdjustPreg (AOP (result));
6392 emitcode ("", "%05d$:", tlbl1->key + 100);
6393 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6396 freeAsmop (left, NULL, ic, TRUE);
6397 freeAsmop (result, NULL, ic, TRUE);
6400 /*-----------------------------------------------------------------*/
6401 /* genRightShift - generate code for right shifting */
6402 /*-----------------------------------------------------------------*/
6404 genRightShift (iCode * ic)
6406 operand *right, *left, *result;
6410 symbol *tlbl, *tlbl1;
6412 /* if signed then we do it the hard way preserve the
6413 sign bit moving it inwards */
6414 retype = getSpec (operandType (IC_RESULT (ic)));
6416 if (!SPEC_USIGN (retype))
6418 genSignedRightShift (ic);
6422 /* signed & unsigned types are treated the same : i.e. the
6423 signed is NOT propagated inwards : quoting from the
6424 ANSI - standard : "for E1 >> E2, is equivalent to division
6425 by 2**E2 if unsigned or if it has a non-negative value,
6426 otherwise the result is implementation defined ", MY definition
6427 is that the sign does not get propagated */
6429 right = IC_RIGHT (ic);
6430 left = IC_LEFT (ic);
6431 result = IC_RESULT (ic);
6433 aopOp (right, ic, FALSE);
6435 /* if the shift count is known then do it
6436 as efficiently as possible */
6437 if (AOP_TYPE (right) == AOP_LIT)
6439 genRightShiftLiteral (left, right, result, ic, 0);
6443 /* shift count is unknown then we have to form
6444 a loop get the loop count in B : Note: we take
6445 only the lower order byte since shifting
6446 more that 32 bits make no sense anyway, ( the
6447 largest size of an object can be only 32 bits ) */
6449 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6450 emitcode ("inc", "b");
6451 freeAsmop (right, NULL, ic, TRUE);
6452 aopOp (left, ic, FALSE);
6453 aopOp (result, ic, FALSE);
6455 /* now move the left to the result if they are not the
6457 if (!sameRegs (AOP (left), AOP (result)) &&
6458 AOP_SIZE (result) > 1)
6461 size = AOP_SIZE (result);
6465 l = aopGet (AOP (left), offset, FALSE, TRUE);
6466 if (*l == '@' && IS_AOP_PREG (result))
6469 emitcode ("mov", "a,%s", l);
6470 aopPut (AOP (result), "a", offset);
6473 aopPut (AOP (result), l, offset);
6478 tlbl = newiTempLabel (NULL);
6479 tlbl1 = newiTempLabel (NULL);
6480 size = AOP_SIZE (result);
6483 /* if it is only one byte then */
6486 l = aopGet (AOP (left), 0, FALSE, FALSE);
6488 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6489 emitcode ("", "%05d$:", tlbl->key + 100);
6491 emitcode ("rrc", "a");
6492 emitcode ("", "%05d$:", tlbl1->key + 100);
6493 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6494 aopPut (AOP (result), "a", 0);
6498 reAdjustPreg (AOP (result));
6499 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6500 emitcode ("", "%05d$:", tlbl->key + 100);
6504 l = aopGet (AOP (result), offset, FALSE, FALSE);
6506 emitcode ("rrc", "a");
6507 aopPut (AOP (result), "a", offset--);
6509 reAdjustPreg (AOP (result));
6511 emitcode ("", "%05d$:", tlbl1->key + 100);
6512 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6515 freeAsmop (left, NULL, ic, TRUE);
6516 freeAsmop (result, NULL, ic, TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* genUnpackBits - generates code for unpacking bits */
6521 /*-----------------------------------------------------------------*/
6523 genUnpackBits (operand * result, char *rname, int ptype)
6531 etype = getSpec (operandType (result));
6532 rsize = getSize (operandType (result));
6533 /* read the first byte */
6539 emitcode ("mov", "a,@%s", rname);
6543 emitcode ("movx", "a,@%s", rname);
6547 emitcode ("movx", "a,@dptr");
6551 emitcode ("clr", "a");
6552 emitcode ("movc", "a,%s", "@a+dptr");
6556 emitcode ("lcall", "__gptrget");
6560 rlen = SPEC_BLEN (etype);
6562 /* if we have bitdisplacement then it fits */
6563 /* into this byte completely or if length is */
6564 /* less than a byte */
6565 if ((shCnt = SPEC_BSTR (etype)) ||
6566 (SPEC_BLEN (etype) <= 8))
6569 /* shift right acc */
6572 emitcode ("anl", "a,#0x%02x",
6573 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6574 aopPut (AOP (result), "a", offset++);
6578 /* bit field did not fit in a byte */
6579 aopPut (AOP (result), "a", offset++);
6588 emitcode ("inc", "%s", rname);
6589 emitcode ("mov", "a,@%s", rname);
6593 emitcode ("inc", "%s", rname);
6594 emitcode ("movx", "a,@%s", rname);
6598 emitcode ("inc", "dptr");
6599 emitcode ("movx", "a,@dptr");
6603 emitcode ("clr", "a");
6604 emitcode ("inc", "dptr");
6605 emitcode ("movc", "a", "@a+dptr");
6609 emitcode ("inc", "dptr");
6610 emitcode ("lcall", "__gptrget");
6615 /* if we are done */
6619 aopPut (AOP (result), "a", offset++);
6625 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6627 aopPut (AOP (result), "a", offset++);
6635 aopPut (AOP (result), zero, offset++);
6641 /*-----------------------------------------------------------------*/
6642 /* genDataPointerGet - generates code when ptr offset is known */
6643 /*-----------------------------------------------------------------*/
6645 genDataPointerGet (operand * left,
6651 int size, offset = 0;
6652 aopOp (result, ic, TRUE);
6654 /* get the string representation of the name */
6655 l = aopGet (AOP (left), 0, FALSE, TRUE);
6656 size = AOP_SIZE (result);
6660 sprintf (buffer, "(%s + %d)", l + 1, offset);
6662 sprintf (buffer, "%s", l + 1);
6663 aopPut (AOP (result), buffer, offset++);
6666 freeAsmop (left, NULL, ic, TRUE);
6667 freeAsmop (result, NULL, ic, TRUE);
6670 /*-----------------------------------------------------------------*/
6671 /* genNearPointerGet - emitcode for near pointer fetch */
6672 /*-----------------------------------------------------------------*/
6674 genNearPointerGet (operand * left,
6682 sym_link *rtype, *retype;
6683 sym_link *ltype = operandType (left);
6686 rtype = operandType (result);
6687 retype = getSpec (rtype);
6689 aopOp (left, ic, FALSE);
6691 /* if left is rematerialisable and
6692 result is not bit variable type and
6693 the left is pointer to data space i.e
6694 lower 128 bytes of space */
6695 if (AOP_TYPE (left) == AOP_IMMD &&
6696 !IS_BITVAR (retype) &&
6697 DCL_TYPE (ltype) == POINTER)
6699 genDataPointerGet (left, result, ic);
6703 /* if the value is already in a pointer register
6704 then don't need anything more */
6705 if (!AOP_INPREG (AOP (left)))
6707 /* otherwise get a free pointer register */
6709 preg = getFreePtr (ic, &aop, FALSE);
6710 emitcode ("mov", "%s,%s",
6712 aopGet (AOP (left), 0, FALSE, TRUE));
6716 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6718 aopOp (result, ic, FALSE);
6720 /* if bitfield then unpack the bits */
6721 if (IS_BITVAR (retype))
6722 genUnpackBits (result, rname, POINTER);
6725 /* we have can just get the values */
6726 int size = AOP_SIZE (result);
6731 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6734 emitcode ("mov", "a,@%s", rname);
6735 aopPut (AOP (result), "a", offset);
6739 sprintf (buffer, "@%s", rname);
6740 aopPut (AOP (result), buffer, offset);
6744 emitcode ("inc", "%s", rname);
6748 /* now some housekeeping stuff */
6749 if (aop) /* we had to allocate for this iCode */
6751 if (pi) { /* post increment present */
6752 aopPut(AOP ( left ),rname,0);
6754 freeAsmop (NULL, aop, ic, TRUE);
6758 /* we did not allocate which means left
6759 already in a pointer register, then
6760 if size > 0 && this could be used again
6761 we have to point it back to where it
6763 if ((AOP_SIZE (result) > 1 &&
6764 !OP_SYMBOL (left)->remat &&
6765 (OP_SYMBOL (left)->liveTo > ic->seq ||
6769 int size = AOP_SIZE (result) - 1;
6771 emitcode ("dec", "%s", rname);
6776 freeAsmop (left, NULL, ic, TRUE);
6777 freeAsmop (result, NULL, ic, TRUE);
6778 if (pi) pi->generated = 1;
6781 /*-----------------------------------------------------------------*/
6782 /* genPagedPointerGet - emitcode for paged pointer fetch */
6783 /*-----------------------------------------------------------------*/
6785 genPagedPointerGet (operand * left,
6793 sym_link *rtype, *retype;
6795 rtype = operandType (result);
6796 retype = getSpec (rtype);
6798 aopOp (left, ic, FALSE);
6800 /* if the value is already in a pointer register
6801 then don't need anything more */
6802 if (!AOP_INPREG (AOP (left)))
6804 /* otherwise get a free pointer register */
6806 preg = getFreePtr (ic, &aop, FALSE);
6807 emitcode ("mov", "%s,%s",
6809 aopGet (AOP (left), 0, FALSE, TRUE));
6813 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6815 aopOp (result, ic, FALSE);
6817 /* if bitfield then unpack the bits */
6818 if (IS_BITVAR (retype))
6819 genUnpackBits (result, rname, PPOINTER);
6822 /* we have can just get the values */
6823 int size = AOP_SIZE (result);
6829 emitcode ("movx", "a,@%s", rname);
6830 aopPut (AOP (result), "a", offset);
6835 emitcode ("inc", "%s", rname);
6839 /* now some housekeeping stuff */
6840 if (aop) /* we had to allocate for this iCode */
6842 if (pi) aopPut ( AOP (left), rname, 0);
6843 freeAsmop (NULL, aop, ic, TRUE);
6847 /* we did not allocate which means left
6848 already in a pointer register, then
6849 if size > 0 && this could be used again
6850 we have to point it back to where it
6852 if ((AOP_SIZE (result) > 1 &&
6853 !OP_SYMBOL (left)->remat &&
6854 (OP_SYMBOL (left)->liveTo > ic->seq ||
6858 int size = AOP_SIZE (result) - 1;
6860 emitcode ("dec", "%s", rname);
6865 freeAsmop (left, NULL, ic, TRUE);
6866 freeAsmop (result, NULL, ic, TRUE);
6867 if (pi) pi->generated = 1;
6871 /*-----------------------------------------------------------------*/
6872 /* genFarPointerGet - gget value from far space */
6873 /*-----------------------------------------------------------------*/
6875 genFarPointerGet (operand * left,
6876 operand * result, iCode * ic, iCode * pi)
6879 sym_link *retype = getSpec (operandType (result));
6881 aopOp (left, ic, FALSE);
6883 /* if the operand is already in dptr
6884 then we do nothing else we move the value to dptr */
6885 if (AOP_TYPE (left) != AOP_STR)
6887 /* if this is remateriazable */
6888 if (AOP_TYPE (left) == AOP_IMMD)
6889 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6891 { /* we need to get it byte by byte */
6892 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6893 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6896 /* so dptr know contains the address */
6897 aopOp (result, ic, FALSE);
6899 /* if bit then unpack */
6900 if (IS_BITVAR (retype))
6901 genUnpackBits (result, "dptr", FPOINTER);
6904 size = AOP_SIZE (result);
6909 emitcode ("movx", "a,@dptr");
6910 aopPut (AOP (result), "a", offset++);
6912 emitcode ("inc", "dptr");
6916 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6917 aopPut ( AOP (left), "dpl", 0);
6918 aopPut ( AOP (left), "dph", 1);
6921 freeAsmop (left, NULL, ic, TRUE);
6922 freeAsmop (result, NULL, ic, TRUE);
6925 /*-----------------------------------------------------------------*/
6926 /* genCodePointerGet - gget value from code space */
6927 /*-----------------------------------------------------------------*/
6929 genCodePointerGet (operand * left,
6930 operand * result, iCode * ic, iCode *pi)
6933 sym_link *retype = getSpec (operandType (result));
6935 aopOp (left, ic, FALSE);
6937 /* if the operand is already in dptr
6938 then we do nothing else we move the value to dptr */
6939 if (AOP_TYPE (left) != AOP_STR)
6941 /* if this is remateriazable */
6942 if (AOP_TYPE (left) == AOP_IMMD)
6943 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6945 { /* we need to get it byte by byte */
6946 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6947 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6950 /* so dptr know contains the address */
6951 aopOp (result, ic, FALSE);
6953 /* if bit then unpack */
6954 if (IS_BITVAR (retype))
6955 genUnpackBits (result, "dptr", CPOINTER);
6958 size = AOP_SIZE (result);
6963 emitcode ("clr", "a");
6964 emitcode ("movc", "a,@a+dptr");
6965 aopPut (AOP (result), "a", offset++);
6967 emitcode ("inc", "dptr");
6971 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6972 aopPut ( AOP (left), "dpl", 0);
6973 aopPut ( AOP (left), "dph", 1);
6976 freeAsmop (left, NULL, ic, TRUE);
6977 freeAsmop (result, NULL, ic, TRUE);
6980 /*-----------------------------------------------------------------*/
6981 /* genGenPointerGet - gget value from generic pointer space */
6982 /*-----------------------------------------------------------------*/
6984 genGenPointerGet (operand * left,
6985 operand * result, iCode * ic, iCode *pi)
6988 sym_link *retype = getSpec (operandType (result));
6990 aopOp (left, ic, FALSE);
6992 /* if the operand is already in dptr
6993 then we do nothing else we move the value to dptr */
6994 if (AOP_TYPE (left) != AOP_STR)
6996 /* if this is remateriazable */
6997 if (AOP_TYPE (left) == AOP_IMMD)
6999 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7000 emitcode ("mov", "b,#%d", pointerCode (retype));
7003 { /* we need to get it byte by byte */
7004 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7005 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7006 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7009 /* so dptr know contains the address */
7010 aopOp (result, ic, FALSE);
7012 /* if bit then unpack */
7013 if (IS_BITVAR (retype))
7014 genUnpackBits (result, "dptr", GPOINTER);
7017 size = AOP_SIZE (result);
7022 emitcode ("lcall", "__gptrget");
7023 aopPut (AOP (result), "a", offset++);
7025 emitcode ("inc", "dptr");
7029 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7030 aopPut ( AOP (left), "dpl", 0);
7031 aopPut ( AOP (left), "dph", 1);
7034 freeAsmop (left, NULL, ic, TRUE);
7035 freeAsmop (result, NULL, ic, TRUE);
7038 /*-----------------------------------------------------------------*/
7039 /* genPointerGet - generate code for pointer get */
7040 /*-----------------------------------------------------------------*/
7042 genPointerGet (iCode * ic, iCode *pi)
7044 operand *left, *result;
7045 sym_link *type, *etype;
7048 left = IC_LEFT (ic);
7049 result = IC_RESULT (ic);
7051 /* depending on the type of pointer we need to
7052 move it to the correct pointer register */
7053 type = operandType (left);
7054 etype = getSpec (type);
7055 /* if left is of type of pointer then it is simple */
7056 if (IS_PTR (type) && !IS_FUNC (type->next))
7057 p_type = DCL_TYPE (type);
7060 /* we have to go by the storage class */
7061 p_type = PTR_TYPE (SPEC_OCLS (etype));
7064 /* now that we have the pointer type we assign
7065 the pointer values */
7071 genNearPointerGet (left, result, ic, pi);
7075 genPagedPointerGet (left, result, ic, pi);
7079 genFarPointerGet (left, result, ic, pi);
7083 genCodePointerGet (left, result, ic, pi);
7087 genGenPointerGet (left, result, ic, pi);
7093 /*-----------------------------------------------------------------*/
7094 /* genPackBits - generates code for packed bit storage */
7095 /*-----------------------------------------------------------------*/
7097 genPackBits (sym_link * etype,
7099 char *rname, int p_type)
7107 blen = SPEC_BLEN (etype);
7108 bstr = SPEC_BSTR (etype);
7110 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7113 /* if the bit lenth is less than or */
7114 /* it exactly fits a byte then */
7115 if (SPEC_BLEN (etype) <= 8)
7117 shCount = SPEC_BSTR (etype);
7119 /* shift left acc */
7122 if (SPEC_BLEN (etype) < 8)
7123 { /* if smaller than a byte */
7129 emitcode ("mov", "b,a");
7130 emitcode ("mov", "a,@%s", rname);
7134 emitcode ("mov", "b,a");
7135 emitcode ("movx", "a,@dptr");
7139 emitcode ("push", "b");
7140 emitcode ("push", "acc");
7141 emitcode ("lcall", "__gptrget");
7142 emitcode ("pop", "b");
7146 emitcode ("anl", "a,#0x%02x", (unsigned char)
7147 ((unsigned char) (0xFF << (blen + bstr)) |
7148 (unsigned char) (0xFF >> (8 - bstr))));
7149 emitcode ("orl", "a,b");
7150 if (p_type == GPOINTER)
7151 emitcode ("pop", "b");
7158 emitcode ("mov", "@%s,a", rname);
7162 emitcode ("movx", "@dptr,a");
7166 emitcode ("lcall", "__gptrput");
7171 if (SPEC_BLEN (etype) <= 8)
7174 emitcode ("inc", "%s", rname);
7175 rLen = SPEC_BLEN (etype);
7177 /* now generate for lengths greater than one byte */
7181 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7193 emitcode ("mov", "@%s,a", rname);
7196 emitcode ("mov", "@%s,%s", rname, l);
7201 emitcode ("movx", "@dptr,a");
7206 emitcode ("lcall", "__gptrput");
7209 emitcode ("inc", "%s", rname);
7214 /* last last was not complete */
7217 /* save the byte & read byte */
7221 emitcode ("mov", "b,a");
7222 emitcode ("mov", "a,@%s", rname);
7226 emitcode ("mov", "b,a");
7227 emitcode ("movx", "a,@dptr");
7231 emitcode ("push", "b");
7232 emitcode ("push", "acc");
7233 emitcode ("lcall", "__gptrget");
7234 emitcode ("pop", "b");
7238 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7239 emitcode ("orl", "a,b");
7242 if (p_type == GPOINTER)
7243 emitcode ("pop", "b");
7249 emitcode ("mov", "@%s,a", rname);
7253 emitcode ("movx", "@dptr,a");
7257 emitcode ("lcall", "__gptrput");
7261 /*-----------------------------------------------------------------*/
7262 /* genDataPointerSet - remat pointer to data space */
7263 /*-----------------------------------------------------------------*/
7265 genDataPointerSet (operand * right,
7269 int size, offset = 0;
7270 char *l, buffer[256];
7272 aopOp (right, ic, FALSE);
7274 l = aopGet (AOP (result), 0, FALSE, TRUE);
7275 size = AOP_SIZE (right);
7279 sprintf (buffer, "(%s + %d)", l + 1, offset);
7281 sprintf (buffer, "%s", l + 1);
7282 emitcode ("mov", "%s,%s", buffer,
7283 aopGet (AOP (right), offset++, FALSE, FALSE));
7286 freeAsmop (right, NULL, ic, TRUE);
7287 freeAsmop (result, NULL, ic, TRUE);
7290 /*-----------------------------------------------------------------*/
7291 /* genNearPointerSet - emitcode for near pointer put */
7292 /*-----------------------------------------------------------------*/
7294 genNearPointerSet (operand * right,
7302 sym_link *retype, *letype;
7303 sym_link *ptype = operandType (result);
7305 retype = getSpec (operandType (right));
7306 letype = getSpec (ptype);
7307 aopOp (result, ic, FALSE);
7309 /* if the result is rematerializable &
7310 in data space & not a bit variable */
7311 if (AOP_TYPE (result) == AOP_IMMD &&
7312 DCL_TYPE (ptype) == POINTER &&
7313 !IS_BITVAR (retype) &&
7314 !IS_BITVAR (letype))
7316 genDataPointerSet (right, result, ic);
7320 /* if the value is already in a pointer register
7321 then don't need anything more */
7322 if (!AOP_INPREG (AOP (result)))
7324 /* otherwise get a free pointer register */
7326 preg = getFreePtr (ic, &aop, FALSE);
7327 emitcode ("mov", "%s,%s",
7329 aopGet (AOP (result), 0, FALSE, TRUE));
7333 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7335 aopOp (right, ic, FALSE);
7337 /* if bitfield then unpack the bits */
7338 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7339 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7342 /* we have can just get the values */
7343 int size = AOP_SIZE (right);
7348 l = aopGet (AOP (right), offset, FALSE, TRUE);
7352 emitcode ("mov", "@%s,a", rname);
7355 emitcode ("mov", "@%s,%s", rname, l);
7357 emitcode ("inc", "%s", rname);
7362 /* now some housekeeping stuff */
7363 if (aop) /* we had to allocate for this iCode */
7365 if (pi) aopPut (AOP (result),rname,0);
7366 freeAsmop (NULL, aop, ic, TRUE);
7370 /* we did not allocate which means left
7371 already in a pointer register, then
7372 if size > 0 && this could be used again
7373 we have to point it back to where it
7375 if ((AOP_SIZE (right) > 1 &&
7376 !OP_SYMBOL (result)->remat &&
7377 (OP_SYMBOL (result)->liveTo > ic->seq ||
7381 int size = AOP_SIZE (right) - 1;
7383 emitcode ("dec", "%s", rname);
7388 if (pi) pi->generated = 1;
7389 freeAsmop (result, NULL, ic, TRUE);
7390 freeAsmop (right, NULL, ic, TRUE);
7393 /*-----------------------------------------------------------------*/
7394 /* genPagedPointerSet - emitcode for Paged pointer put */
7395 /*-----------------------------------------------------------------*/
7397 genPagedPointerSet (operand * right,
7405 sym_link *retype, *letype;
7407 retype = getSpec (operandType (right));
7408 letype = getSpec (operandType (result));
7410 aopOp (result, ic, FALSE);
7412 /* if the value is already in a pointer register
7413 then don't need anything more */
7414 if (!AOP_INPREG (AOP (result)))
7416 /* otherwise get a free pointer register */
7418 preg = getFreePtr (ic, &aop, FALSE);
7419 emitcode ("mov", "%s,%s",
7421 aopGet (AOP (result), 0, FALSE, TRUE));
7425 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7427 aopOp (right, ic, FALSE);
7429 /* if bitfield then unpack the bits */
7430 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7431 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7434 /* we have can just get the values */
7435 int size = AOP_SIZE (right);
7440 l = aopGet (AOP (right), offset, FALSE, TRUE);
7443 emitcode ("movx", "@%s,a", rname);
7446 emitcode ("inc", "%s", rname);
7452 /* now some housekeeping stuff */
7453 if (aop) /* we had to allocate for this iCode */
7455 if (pi) aopPut (AOP (result),rname,0);
7456 freeAsmop (NULL, aop, ic, TRUE);
7460 /* we did not allocate which means left
7461 already in a pointer register, then
7462 if size > 0 && this could be used again
7463 we have to point it back to where it
7465 if (AOP_SIZE (right) > 1 &&
7466 !OP_SYMBOL (result)->remat &&
7467 (OP_SYMBOL (result)->liveTo > ic->seq ||
7470 int size = AOP_SIZE (right) - 1;
7472 emitcode ("dec", "%s", rname);
7477 if (pi) pi->generated = 1;
7478 freeAsmop (result, NULL, ic, TRUE);
7479 freeAsmop (right, NULL, ic, TRUE);
7484 /*-----------------------------------------------------------------*/
7485 /* genFarPointerSet - set value from far space */
7486 /*-----------------------------------------------------------------*/
7488 genFarPointerSet (operand * right,
7489 operand * result, iCode * ic, iCode * pi)
7492 sym_link *retype = getSpec (operandType (right));
7493 sym_link *letype = getSpec (operandType (result));
7494 aopOp (result, ic, FALSE);
7496 /* if the operand is already in dptr
7497 then we do nothing else we move the value to dptr */
7498 if (AOP_TYPE (result) != AOP_STR)
7500 /* if this is remateriazable */
7501 if (AOP_TYPE (result) == AOP_IMMD)
7502 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7504 { /* we need to get it byte by byte */
7505 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7506 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7509 /* so dptr know contains the address */
7510 aopOp (right, ic, FALSE);
7512 /* if bit then unpack */
7513 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7514 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7517 size = AOP_SIZE (right);
7522 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7524 emitcode ("movx", "@dptr,a");
7526 emitcode ("inc", "dptr");
7529 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7530 aopPut (AOP(result),"dpl",0);
7531 aopPut (AOP(result),"dph",1);
7534 freeAsmop (result, NULL, ic, TRUE);
7535 freeAsmop (right, NULL, ic, TRUE);
7538 /*-----------------------------------------------------------------*/
7539 /* genGenPointerSet - set value from generic pointer space */
7540 /*-----------------------------------------------------------------*/
7542 genGenPointerSet (operand * right,
7543 operand * result, iCode * ic, iCode * pi)
7546 sym_link *retype = getSpec (operandType (right));
7547 sym_link *letype = getSpec (operandType (result));
7549 aopOp (result, ic, FALSE);
7551 /* if the operand is already in dptr
7552 then we do nothing else we move the value to dptr */
7553 if (AOP_TYPE (result) != AOP_STR)
7555 /* if this is remateriazable */
7556 if (AOP_TYPE (result) == AOP_IMMD)
7558 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7559 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7562 { /* we need to get it byte by byte */
7563 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7564 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7565 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7568 /* so dptr know contains the address */
7569 aopOp (right, ic, FALSE);
7571 /* if bit then unpack */
7572 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7573 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7576 size = AOP_SIZE (right);
7581 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7583 emitcode ("lcall", "__gptrput");
7585 emitcode ("inc", "dptr");
7589 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7590 aopPut (AOP(result),"dpl",0);
7591 aopPut (AOP(result),"dph",1);
7594 freeAsmop (result, NULL, ic, TRUE);
7595 freeAsmop (right, NULL, ic, TRUE);
7598 /*-----------------------------------------------------------------*/
7599 /* genPointerSet - stores the value into a pointer location */
7600 /*-----------------------------------------------------------------*/
7602 genPointerSet (iCode * ic, iCode *pi)
7604 operand *right, *result;
7605 sym_link *type, *etype;
7608 right = IC_RIGHT (ic);
7609 result = IC_RESULT (ic);
7611 /* depending on the type of pointer we need to
7612 move it to the correct pointer register */
7613 type = operandType (result);
7614 etype = getSpec (type);
7615 /* if left is of type of pointer then it is simple */
7616 if (IS_PTR (type) && !IS_FUNC (type->next))
7618 p_type = DCL_TYPE (type);
7622 /* we have to go by the storage class */
7623 p_type = PTR_TYPE (SPEC_OCLS (etype));
7626 /* now that we have the pointer type we assign
7627 the pointer values */
7633 genNearPointerSet (right, result, ic, pi);
7637 genPagedPointerSet (right, result, ic, pi);
7641 genFarPointerSet (right, result, ic, pi);
7645 genGenPointerSet (right, result, ic, pi);
7651 /*-----------------------------------------------------------------*/
7652 /* genIfx - generate code for Ifx statement */
7653 /*-----------------------------------------------------------------*/
7655 genIfx (iCode * ic, iCode * popIc)
7657 operand *cond = IC_COND (ic);
7660 aopOp (cond, ic, FALSE);
7662 /* get the value into acc */
7663 if (AOP_TYPE (cond) != AOP_CRY)
7667 /* the result is now in the accumulator */
7668 freeAsmop (cond, NULL, ic, TRUE);
7670 /* if there was something to be popped then do it */
7674 /* if the condition is a bit variable */
7675 if (isbit && IS_ITEMP (cond) &&
7677 genIfxJump (ic, SPIL_LOC (cond)->rname);
7678 else if (isbit && !IS_ITEMP (cond))
7679 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7681 genIfxJump (ic, "a");
7686 /*-----------------------------------------------------------------*/
7687 /* genAddrOf - generates code for address of */
7688 /*-----------------------------------------------------------------*/
7690 genAddrOf (iCode * ic)
7692 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7695 aopOp (IC_RESULT (ic), ic, FALSE);
7697 /* if the operand is on the stack then we
7698 need to get the stack offset of this
7702 /* if it has an offset then we need to compute
7706 emitcode ("mov", "a,_bp");
7707 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7708 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7712 /* we can just move _bp */
7713 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7715 /* fill the result with zero */
7716 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7721 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7727 /* object not on stack then we need the name */
7728 size = AOP_SIZE (IC_RESULT (ic));
7733 char s[SDCC_NAME_MAX];
7735 sprintf (s, "#(%s >> %d)",
7739 sprintf (s, "#%s", sym->rname);
7740 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7744 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7748 /*-----------------------------------------------------------------*/
7749 /* genFarFarAssign - assignment when both are in far space */
7750 /*-----------------------------------------------------------------*/
7752 genFarFarAssign (operand * result, operand * right, iCode * ic)
7754 int size = AOP_SIZE (right);
7757 /* first push the right side on to the stack */
7760 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7762 emitcode ("push", "acc");
7765 freeAsmop (right, NULL, ic, FALSE);
7766 /* now assign DPTR to result */
7767 aopOp (result, ic, FALSE);
7768 size = AOP_SIZE (result);
7771 emitcode ("pop", "acc");
7772 aopPut (AOP (result), "a", --offset);
7774 freeAsmop (result, NULL, ic, FALSE);
7778 /*-----------------------------------------------------------------*/
7779 /* genAssign - generate code for assignment */
7780 /*-----------------------------------------------------------------*/
7782 genAssign (iCode * ic)
7784 operand *result, *right;
7786 unsigned long lit = 0L;
7788 result = IC_RESULT (ic);
7789 right = IC_RIGHT (ic);
7791 /* if they are the same */
7792 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7795 aopOp (right, ic, FALSE);
7797 /* special case both in far space */
7798 if (AOP_TYPE (right) == AOP_DPTR &&
7799 IS_TRUE_SYMOP (result) &&
7800 isOperandInFarSpace (result))
7803 genFarFarAssign (result, right, ic);
7807 aopOp (result, ic, TRUE);
7809 /* if they are the same registers */
7810 if (sameRegs (AOP (right), AOP (result)))
7813 /* if the result is a bit */
7814 if (AOP_TYPE (result) == AOP_CRY)
7817 /* if the right size is a literal then
7818 we know what the value is */
7819 if (AOP_TYPE (right) == AOP_LIT)
7821 if (((int) operandLitValue (right)))
7822 aopPut (AOP (result), one, 0);
7824 aopPut (AOP (result), zero, 0);
7828 /* the right is also a bit variable */
7829 if (AOP_TYPE (right) == AOP_CRY)
7831 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7832 aopPut (AOP (result), "c", 0);
7838 aopPut (AOP (result), "a", 0);
7842 /* bit variables done */
7844 size = AOP_SIZE (result);
7846 if (AOP_TYPE (right) == AOP_LIT)
7847 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7849 (AOP_TYPE (result) != AOP_REG) &&
7850 (AOP_TYPE (right) == AOP_LIT) &&
7851 !IS_FLOAT (operandType (right)) &&
7854 emitcode ("clr", "a");
7857 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7858 aopPut (AOP (result), "a", size);
7860 aopPut (AOP (result),
7861 aopGet (AOP (right), size, FALSE, FALSE),
7869 aopPut (AOP (result),
7870 aopGet (AOP (right), offset, FALSE, FALSE),
7877 freeAsmop (right, NULL, ic, TRUE);
7878 freeAsmop (result, NULL, ic, TRUE);
7881 /*-----------------------------------------------------------------*/
7882 /* genJumpTab - genrates code for jump table */
7883 /*-----------------------------------------------------------------*/
7885 genJumpTab (iCode * ic)
7890 aopOp (IC_JTCOND (ic), ic, FALSE);
7891 /* get the condition into accumulator */
7892 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7894 /* multiply by three */
7895 emitcode ("add", "a,acc");
7896 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7897 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7899 jtab = newiTempLabel (NULL);
7900 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7901 emitcode ("jmp", "@a+dptr");
7902 emitcode ("", "%05d$:", jtab->key + 100);
7903 /* now generate the jump labels */
7904 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7905 jtab = setNextItem (IC_JTLABELS (ic)))
7906 emitcode ("ljmp", "%05d$", jtab->key + 100);
7910 /*-----------------------------------------------------------------*/
7911 /* genCast - gen code for casting */
7912 /*-----------------------------------------------------------------*/
7914 genCast (iCode * ic)
7916 operand *result = IC_RESULT (ic);
7917 sym_link *ctype = operandType (IC_LEFT (ic));
7918 sym_link *rtype = operandType (IC_RIGHT (ic));
7919 operand *right = IC_RIGHT (ic);
7922 /* if they are equivalent then do nothing */
7923 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7926 aopOp (right, ic, FALSE);
7927 aopOp (result, ic, FALSE);
7929 /* if the result is a bit */
7930 if (AOP_TYPE (result) == AOP_CRY)
7932 /* if the right size is a literal then
7933 we know what the value is */
7934 if (AOP_TYPE (right) == AOP_LIT)
7936 if (((int) operandLitValue (right)))
7937 aopPut (AOP (result), one, 0);
7939 aopPut (AOP (result), zero, 0);
7944 /* the right is also a bit variable */
7945 if (AOP_TYPE (right) == AOP_CRY)
7947 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7948 aopPut (AOP (result), "c", 0);
7954 aopPut (AOP (result), "a", 0);
7958 /* if they are the same size : or less */
7959 if (AOP_SIZE (result) <= AOP_SIZE (right))
7962 /* if they are in the same place */
7963 if (sameRegs (AOP (right), AOP (result)))
7966 /* if they in different places then copy */
7967 size = AOP_SIZE (result);
7971 aopPut (AOP (result),
7972 aopGet (AOP (right), offset, FALSE, FALSE),
7980 /* if the result is of type pointer */
7985 sym_link *type = operandType (right);
7986 sym_link *etype = getSpec (type);
7988 /* pointer to generic pointer */
7989 if (IS_GENPTR (ctype))
7994 p_type = DCL_TYPE (type);
7997 /* we have to go by the storage class */
7998 p_type = PTR_TYPE (SPEC_OCLS (etype));
8001 /* the first two bytes are known */
8002 size = GPTRSIZE - 1;
8006 aopPut (AOP (result),
8007 aopGet (AOP (right), offset, FALSE, FALSE),
8011 /* the last byte depending on type */
8029 /* this should never happen */
8030 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8031 "got unknown pointer type");
8034 aopPut (AOP (result), l, GPTRSIZE - 1);
8038 /* just copy the pointers */
8039 size = AOP_SIZE (result);
8043 aopPut (AOP (result),
8044 aopGet (AOP (right), offset, FALSE, FALSE),
8051 /* so we now know that the size of destination is greater
8052 than the size of the source */
8053 /* we move to result for the size of source */
8054 size = AOP_SIZE (right);
8058 aopPut (AOP (result),
8059 aopGet (AOP (right), offset, FALSE, FALSE),
8064 /* now depending on the sign of the source && destination */
8065 size = AOP_SIZE (result) - AOP_SIZE (right);
8066 /* if unsigned or not an integral type */
8067 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8070 aopPut (AOP (result), zero, offset++);
8074 /* we need to extend the sign :{ */
8075 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8078 emitcode ("rlc", "a");
8079 emitcode ("subb", "a,acc");
8081 aopPut (AOP (result), "a", offset++);
8084 /* we are done hurray !!!! */
8087 freeAsmop (right, NULL, ic, TRUE);
8088 freeAsmop (result, NULL, ic, TRUE);
8092 /*-----------------------------------------------------------------*/
8093 /* genDjnz - generate decrement & jump if not zero instrucion */
8094 /*-----------------------------------------------------------------*/
8096 genDjnz (iCode * ic, iCode * ifx)
8102 /* if the if condition has a false label
8103 then we cannot save */
8107 /* if the minus is not of the form
8109 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8110 !IS_OP_LITERAL (IC_RIGHT (ic)))
8113 if (operandLitValue (IC_RIGHT (ic)) != 1)
8116 /* if the size of this greater than one then no
8118 if (getSize (operandType (IC_RESULT (ic))) > 1)
8121 /* otherwise we can save BIG */
8122 lbl = newiTempLabel (NULL);
8123 lbl1 = newiTempLabel (NULL);
8125 aopOp (IC_RESULT (ic), ic, FALSE);
8127 if (IS_AOP_PREG (IC_RESULT (ic)))
8129 emitcode ("dec", "%s",
8130 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8131 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8132 emitcode ("jnz", "%05d$", lbl->key + 100);
8136 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8139 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8140 emitcode ("", "%05d$:", lbl->key + 100);
8141 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8142 emitcode ("", "%05d$:", lbl1->key + 100);
8144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8149 /*-----------------------------------------------------------------*/
8150 /* genReceive - generate code for a receive iCode */
8151 /*-----------------------------------------------------------------*/
8153 genReceive (iCode * ic)
8155 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8156 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8157 IS_TRUE_SYMOP (IC_RESULT (ic))))
8160 int size = getSize (operandType (IC_RESULT (ic)));
8161 int offset = fReturnSizeMCS51 - size;
8164 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8165 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8168 aopOp (IC_RESULT (ic), ic, FALSE);
8169 size = AOP_SIZE (IC_RESULT (ic));
8173 emitcode ("pop", "acc");
8174 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8181 aopOp (IC_RESULT (ic), ic, FALSE);
8183 assignResultValue (IC_RESULT (ic));
8186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8189 /*-----------------------------------------------------------------*/
8190 /* gen51Code - generate code for 8051 based controllers */
8191 /*-----------------------------------------------------------------*/
8193 gen51Code (iCode * lic)
8198 lineHead = lineCurr = NULL;
8200 /* print the allocation information */
8202 printAllocInfo (currFunc, codeOutFile);
8203 /* if debug information required */
8204 /* if (options.debug && currFunc) { */
8207 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8209 if (IS_STATIC (currFunc->etype))
8210 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8212 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8215 /* stack pointer name */
8216 if (options.useXstack)
8222 for (ic = lic; ic; ic = ic->next)
8225 if (cln != ic->lineno)
8230 emitcode ("", "C$%s$%d$%d$%d ==.",
8231 FileBaseName (ic->filename), ic->lineno,
8232 ic->level, ic->block);
8235 emitcode (";", "%s %d", ic->filename, ic->lineno);
8238 /* if the result is marked as
8239 spilt and rematerializable or code for
8240 this has already been generated then
8242 if (resultRemat (ic) || ic->generated)
8245 /* depending on the operation */
8265 /* IPOP happens only when trying to restore a
8266 spilt live range, if there is an ifx statement
8267 following this pop then the if statement might
8268 be using some of the registers being popped which
8269 would destory the contents of the register so
8270 we need to check for this condition and handle it */
8272 ic->next->op == IFX &&
8273 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8274 genIfx (ic->next, ic);
8292 genEndFunction (ic);
8312 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8329 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8333 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8340 /* note these two are xlated by algebraic equivalence
8341 during parsing SDCC.y */
8342 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8343 "got '>=' or '<=' shouldn't have come here");
8347 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8359 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8363 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8367 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8394 case GET_VALUE_AT_ADDRESS:
8395 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8399 if (POINTER_SET (ic))
8400 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8426 addSet (&_G.sendSet, ic);
8435 /* now we are ready to call the
8436 peep hole optimizer */
8437 if (!options.nopeep)
8438 peepHole (&lineHead);
8440 /* now do the actual printing */
8441 printLine (lineHead, codeOutFile);