1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[INITIAL_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1451 /* find the registers in use at this time
1452 and push them away to safety */
1453 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1457 if (options.useXstack)
1459 if (bitVectBitValue (rsave, R0_IDX))
1460 emitcode ("mov", "b,r0");
1461 emitcode ("mov", "r0,%s", spname);
1462 for (i = 0; i < mcs51_nRegs; i++)
1464 if (bitVectBitValue (rsave, i))
1467 emitcode ("mov", "a,b");
1469 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1470 emitcode ("movx", "@r0,a");
1471 emitcode ("inc", "r0");
1474 emitcode ("mov", "%s,r0", spname);
1475 if (bitVectBitValue (rsave, R0_IDX))
1476 emitcode ("mov", "r0,b");
1479 for (i = 0; i < mcs51_nRegs; i++)
1481 if (bitVectBitValue (rsave, i))
1482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1485 detype = getSpec (operandType (IC_LEFT (ic)));
1487 #if 0 // why should we do this here??? jwk20011105
1489 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1490 IS_ISR (currFunc->etype) &&
1492 saveRBank (SPEC_BANK (detype), ic, TRUE);
1496 /*-----------------------------------------------------------------*/
1497 /* unsaveRegisters - pop the pushed registers */
1498 /*-----------------------------------------------------------------*/
1500 unsaveRegisters (iCode * ic)
1504 /* find the registers in use at this time
1505 and push them away to safety */
1506 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1509 if (options.useXstack)
1511 emitcode ("mov", "r0,%s", spname);
1512 for (i = mcs51_nRegs; i >= 0; i--)
1514 if (bitVectBitValue (rsave, i))
1516 emitcode ("dec", "r0");
1517 emitcode ("movx", "a,@r0");
1519 emitcode ("mov", "b,a");
1521 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = mcs51_nRegs; i >= 0; i--)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1539 /*-----------------------------------------------------------------*/
1541 /*-----------------------------------------------------------------*/
1543 pushSide (operand * oper, int size)
1548 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1549 if (AOP_TYPE (oper) != AOP_REG &&
1550 AOP_TYPE (oper) != AOP_DIR &&
1553 emitcode ("mov", "a,%s", l);
1554 emitcode ("push", "acc");
1557 emitcode ("push", "%s", l);
1561 /*-----------------------------------------------------------------*/
1562 /* assignResultValue - */
1563 /*-----------------------------------------------------------------*/
1565 assignResultValue (operand * oper)
1568 int size = AOP_SIZE (oper);
1571 aopPut (AOP (oper), fReturn[offset], offset);
1577 /*-----------------------------------------------------------------*/
1578 /* genXpush - pushes onto the external stack */
1579 /*-----------------------------------------------------------------*/
1581 genXpush (iCode * ic)
1583 asmop *aop = newAsmop (0);
1585 int size, offset = 0;
1587 aopOp (IC_LEFT (ic), ic, FALSE);
1588 r = getFreePtr (ic, &aop, FALSE);
1591 emitcode ("mov", "%s,_spx", r->name);
1593 size = AOP_SIZE (IC_LEFT (ic));
1597 char *l = aopGet (AOP (IC_LEFT (ic)),
1598 offset++, FALSE, FALSE);
1600 emitcode ("movx", "@%s,a", r->name);
1601 emitcode ("inc", "%s", r->name);
1606 emitcode ("mov", "_spx,%s", r->name);
1608 freeAsmop (NULL, aop, ic, TRUE);
1609 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1612 /*-----------------------------------------------------------------*/
1613 /* genIpush - genrate code for pushing this gets a little complex */
1614 /*-----------------------------------------------------------------*/
1616 genIpush (iCode * ic)
1618 int size, offset = 0;
1621 /* if this is not a parm push : ie. it is spill push
1622 and spill push is always done on the local stack */
1626 /* and the item is spilt then do nothing */
1627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1630 aopOp (IC_LEFT (ic), ic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (ic));
1632 /* push it on the stack */
1635 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1641 emitcode ("push", "%s", l);
1646 /* this is a paramter push: in this case we call
1647 the routine to find the call and save those
1648 registers that need to be saved */
1651 /* if use external stack then call the external
1652 stack pushing routine */
1653 if (options.useXstack)
1659 /* then do the push */
1660 aopOp (IC_LEFT (ic), ic, FALSE);
1663 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1664 size = AOP_SIZE (IC_LEFT (ic));
1668 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1669 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1670 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1673 emitcode ("mov", "a,%s", l);
1674 emitcode ("push", "acc");
1677 emitcode ("push", "%s", l);
1680 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1683 /*-----------------------------------------------------------------*/
1684 /* genIpop - recover the registers: can happen only for spilling */
1685 /*-----------------------------------------------------------------*/
1687 genIpop (iCode * ic)
1692 /* if the temp was not pushed then */
1693 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1696 aopOp (IC_LEFT (ic), ic, FALSE);
1697 size = AOP_SIZE (IC_LEFT (ic));
1698 offset = (size - 1);
1700 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1703 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* unsaveRBank - restores the resgister bank from stack */
1708 /*-----------------------------------------------------------------*/
1710 unsaveRBank (int bank, iCode * ic, bool popPsw)
1716 if (options.useXstack)
1720 /* Assume r0 is available for use. */
1721 r = mcs51_regWithIdx (R0_IDX);;
1726 r = getFreePtr (ic, &aop, FALSE);
1728 emitcode ("mov", "%s,_spx", r->name);
1733 if (options.useXstack)
1735 emitcode ("movx", "a,@%s", r->name);
1736 emitcode ("mov", "psw,a");
1737 emitcode ("dec", "%s", r->name);
1741 emitcode ("pop", "psw");
1745 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1747 if (options.useXstack)
1749 emitcode ("movx", "a,@%s", r->name);
1750 emitcode ("mov", "(%s+%d),a",
1751 regs8051[i].base, 8 * bank + regs8051[i].offset);
1752 emitcode ("dec", "%s", r->name);
1756 emitcode ("pop", "(%s+%d)",
1757 regs8051[i].base, 8 * bank + regs8051[i].offset);
1760 if (options.useXstack)
1762 emitcode ("mov", "_spx,%s", r->name);
1767 freeAsmop (NULL, aop, ic, TRUE);
1771 /*-----------------------------------------------------------------*/
1772 /* saveRBank - saves an entire register bank on the stack */
1773 /*-----------------------------------------------------------------*/
1775 saveRBank (int bank, iCode * ic, bool pushPsw)
1781 if (options.useXstack)
1785 /* Assume r0 is available for use. */
1786 r = mcs51_regWithIdx (R0_IDX);;
1791 r = getFreePtr (ic, &aop, FALSE);
1793 emitcode ("mov", "%s,_spx", r->name);
1796 for (i = 0; i < mcs51_nRegs; i++)
1798 if (options.useXstack)
1800 emitcode ("inc", "%s", r->name);
1801 emitcode ("mov", "a,(%s+%d)",
1802 regs8051[i].base, 8 * bank + regs8051[i].offset);
1803 emitcode ("movx", "@%s,a", r->name);
1806 emitcode ("push", "(%s+%d)",
1807 regs8051[i].base, 8 * bank + regs8051[i].offset);
1812 if (options.useXstack)
1814 emitcode ("mov", "a,psw");
1815 emitcode ("movx", "@%s,a", r->name);
1816 emitcode ("inc", "%s", r->name);
1817 emitcode ("mov", "_spx,%s", r->name);
1822 emitcode ("push", "psw");
1825 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1830 freeAsmop (NULL, aop, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genCall - generates a call statement */
1841 /*-----------------------------------------------------------------*/
1843 genCall (iCode * ic)
1846 bool restoreBank = FALSE;
1847 bool swapBanks = FALSE;
1849 /* if send set is not empty the assign */
1854 for (sic = setFirstItem (_G.sendSet); sic;
1855 sic = setNextItem (_G.sendSet))
1857 int size, offset = 0;
1858 aopOp (IC_LEFT (sic), sic, FALSE);
1859 size = AOP_SIZE (IC_LEFT (sic));
1862 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1864 if (strcmp (l, fReturn[offset]))
1865 emitcode ("mov", "%s,%s",
1870 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1875 /* if we are calling a function that is not using
1876 the same register bank then we need to save the
1877 destination registers on the stack */
1878 detype = getSpec (operandType (IC_LEFT (ic)));
1880 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1881 IS_ISR (currFunc->etype))
1885 /* This is unexpected; the bank should have been saved in
1888 saveRBank (SPEC_BANK (detype), ic, FALSE);
1894 /* if caller saves & we have not saved then */
1900 emitcode ("mov", "psw,#0x%02x",
1901 ((SPEC_BANK(detype)) << 3) & 0xff);
1905 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1906 OP_SYMBOL (IC_LEFT (ic))->rname :
1907 OP_SYMBOL (IC_LEFT (ic))->name));
1911 emitcode ("mov", "psw,#0x%02x",
1912 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1915 /* if we need assign a result value */
1916 if ((IS_ITEMP (IC_RESULT (ic)) &&
1917 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1918 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1919 IS_TRUE_SYMOP (IC_RESULT (ic)))
1923 aopOp (IC_RESULT (ic), ic, FALSE);
1926 assignResultValue (IC_RESULT (ic));
1928 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1931 /* adjust the stack for parameters if
1936 if (ic->parmBytes > 3)
1938 emitcode ("mov", "a,%s", spname);
1939 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1940 emitcode ("mov", "%s,a", spname);
1943 for (i = 0; i < ic->parmBytes; i++)
1944 emitcode ("dec", "%s", spname);
1947 /* if we hade saved some registers then unsave them */
1948 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1949 unsaveRegisters (ic);
1951 /* if register bank was saved then pop them */
1953 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1956 /*-----------------------------------------------------------------*/
1957 /* genPcall - generates a call by pointer statement */
1958 /*-----------------------------------------------------------------*/
1960 genPcall (iCode * ic)
1963 symbol *rlbl = newiTempLabel (NULL);
1966 /* if caller saves & we have not saved then */
1970 /* if we are calling a function that is not using
1971 the same register bank then we need to save the
1972 destination registers on the stack */
1973 detype = getSpec (operandType (IC_LEFT (ic)));
1975 IS_ISR (currFunc->etype) &&
1976 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1977 saveRBank (SPEC_BANK (detype), ic, TRUE);
1980 /* push the return address on to the stack */
1981 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1982 emitcode ("push", "acc");
1983 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1984 emitcode ("push", "acc");
1986 /* now push the calling address */
1987 aopOp (IC_LEFT (ic), ic, FALSE);
1989 pushSide (IC_LEFT (ic), FPTRSIZE);
1991 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1993 /* if send set is not empty the assign */
1998 for (sic = setFirstItem (_G.sendSet); sic;
1999 sic = setNextItem (_G.sendSet))
2001 int size, offset = 0;
2002 aopOp (IC_LEFT (sic), sic, FALSE);
2003 size = AOP_SIZE (IC_LEFT (sic));
2006 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2008 if (strcmp (l, fReturn[offset]))
2009 emitcode ("mov", "%s,%s",
2014 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2019 emitcode ("ret", "");
2020 emitcode ("", "%05d$:", (rlbl->key + 100));
2023 /* if we need assign a result value */
2024 if ((IS_ITEMP (IC_RESULT (ic)) &&
2025 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2026 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2027 IS_TRUE_SYMOP (IC_RESULT (ic)))
2031 aopOp (IC_RESULT (ic), ic, FALSE);
2034 assignResultValue (IC_RESULT (ic));
2036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2039 /* adjust the stack for parameters if
2044 if (ic->parmBytes > 3)
2046 emitcode ("mov", "a,%s", spname);
2047 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2048 emitcode ("mov", "%s,a", spname);
2051 for (i = 0; i < ic->parmBytes; i++)
2052 emitcode ("dec", "%s", spname);
2056 /* if register bank was saved then unsave them */
2058 (SPEC_BANK (currFunc->etype) !=
2059 SPEC_BANK (detype)))
2060 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2062 /* if we hade saved some registers then
2065 unsaveRegisters (ic);
2069 /*-----------------------------------------------------------------*/
2070 /* resultRemat - result is rematerializable */
2071 /*-----------------------------------------------------------------*/
2073 resultRemat (iCode * ic)
2075 if (SKIP_IC (ic) || ic->op == IFX)
2078 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2080 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2081 if (sym->remat && !POINTER_SET (ic))
2088 #if defined(__BORLANDC__) || defined(_MSC_VER)
2089 #define STRCASECMP stricmp
2091 #define STRCASECMP strcasecmp
2094 /*-----------------------------------------------------------------*/
2095 /* inExcludeList - return 1 if the string is in exclude Reg list */
2096 /*-----------------------------------------------------------------*/
2098 inExcludeList (char *s)
2102 if (options.excludeRegs[i] &&
2103 STRCASECMP (options.excludeRegs[i], "none") == 0)
2106 for (i = 0; options.excludeRegs[i]; i++)
2108 if (options.excludeRegs[i] &&
2109 STRCASECMP (s, options.excludeRegs[i]) == 0)
2115 /*-----------------------------------------------------------------*/
2116 /* genFunction - generated code for function entry */
2117 /*-----------------------------------------------------------------*/
2119 genFunction (iCode * ic)
2123 bool switchedPSW = FALSE;
2126 /* create the function header */
2127 emitcode (";", "-----------------------------------------");
2128 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2129 emitcode (";", "-----------------------------------------");
2131 emitcode ("", "%s:", sym->rname);
2132 fetype = getSpec (operandType (IC_LEFT (ic)));
2134 if (SPEC_NAKED(fetype))
2136 emitcode(";", "naked function: no prologue.");
2140 /* if critical function then turn interrupts off */
2141 if (SPEC_CRTCL (fetype))
2142 emitcode ("clr", "ea");
2144 /* here we need to generate the equates for the
2145 register bank if required */
2146 if (SPEC_BANK (fetype) != rbank)
2150 rbank = SPEC_BANK (fetype);
2151 for (i = 0; i < mcs51_nRegs; i++)
2153 if (strcmp (regs8051[i].base, "0") == 0)
2154 emitcode ("", "%s = 0x%02x",
2156 8 * rbank + regs8051[i].offset);
2158 emitcode ("", "%s = %s + 0x%02x",
2161 8 * rbank + regs8051[i].offset);
2165 /* if this is an interrupt service routine then
2166 save acc, b, dpl, dph */
2167 if (IS_ISR (sym->etype))
2170 if (!inExcludeList ("acc"))
2171 emitcode ("push", "acc");
2172 if (!inExcludeList ("b"))
2173 emitcode ("push", "b");
2174 if (!inExcludeList ("dpl"))
2175 emitcode ("push", "dpl");
2176 if (!inExcludeList ("dph"))
2177 emitcode ("push", "dph");
2178 /* if this isr has no bank i.e. is going to
2179 run with bank 0 , then we need to save more
2181 if (!SPEC_BANK (sym->etype))
2184 /* if this function does not call any other
2185 function then we can be economical and
2186 save only those registers that are used */
2191 /* if any registers used */
2194 /* save the registers used */
2195 for (i = 0; i < sym->regsUsed->size; i++)
2197 if (bitVectBitValue (sym->regsUsed, i) ||
2198 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2199 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2206 /* this function has a function call cannot
2207 determines register usage so we will have to push the
2209 saveRBank (0, ic, FALSE);
2214 /* This ISR uses a non-zero bank.
2216 * We assume that the bank is available for our
2219 * However, if this ISR calls a function which uses some
2220 * other bank, we must save that bank entirely.
2222 unsigned long banksToSave = 0;
2227 #define MAX_REGISTER_BANKS 4
2232 for (i = ic; i; i = i->next)
2234 if (i->op == ENDFUNCTION)
2236 /* we got to the end OK. */
2244 detype = getSpec(operandType (IC_LEFT(i)));
2246 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2248 /* Mark this bank for saving. */
2249 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2251 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2255 banksToSave |= (1 << SPEC_BANK(detype));
2258 /* And note that we don't need to do it in
2266 /* This is a mess; we have no idea what
2267 * register bank the called function might
2270 * The only thing I can think of to do is
2271 * throw a warning and hope.
2273 werror(W_FUNCPTR_IN_USING_ISR);
2277 if (banksToSave && options.useXstack)
2279 /* Since we aren't passing it an ic,
2280 * saveRBank will assume r0 is available to abuse.
2282 * So switch to our (trashable) bank now, so
2283 * the caller's R0 isn't trashed.
2285 emitcode ("push", "psw");
2286 emitcode ("mov", "psw,#0x%02x",
2287 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2291 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2293 if (banksToSave & (1 << ix))
2295 saveRBank(ix, NULL, FALSE);
2299 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2304 /* if callee-save to be used for this function
2305 then save the registers being used in this function */
2306 if (sym->calleeSave)
2310 /* if any registers used */
2313 /* save the registers used */
2314 for (i = 0; i < sym->regsUsed->size; i++)
2316 if (bitVectBitValue (sym->regsUsed, i) ||
2317 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2319 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2327 /* set the register bank to the desired value */
2328 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2331 emitcode ("push", "psw");
2332 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2335 if (IS_RENT (sym->etype) || options.stackAuto)
2338 if (options.useXstack)
2340 emitcode ("mov", "r0,%s", spname);
2341 emitcode ("mov", "a,_bp");
2342 emitcode ("movx", "@r0,a");
2343 emitcode ("inc", "%s", spname);
2347 /* set up the stack */
2348 emitcode ("push", "_bp"); /* save the callers stack */
2350 emitcode ("mov", "_bp,%s", spname);
2353 /* adjust the stack for the function */
2359 werror (W_STACK_OVERFLOW, sym->name);
2361 if (i > 3 && sym->recvSize < 4)
2364 emitcode ("mov", "a,sp");
2365 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2366 emitcode ("mov", "sp,a");
2371 emitcode ("inc", "sp");
2377 emitcode ("mov", "a,_spx");
2378 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2379 emitcode ("mov", "_spx,a");
2384 /*-----------------------------------------------------------------*/
2385 /* genEndFunction - generates epilogue for functions */
2386 /*-----------------------------------------------------------------*/
2388 genEndFunction (iCode * ic)
2390 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2392 if (SPEC_NAKED(sym->etype))
2394 emitcode(";", "naked function: no epilogue.");
2398 if (IS_RENT (sym->etype) || options.stackAuto)
2400 emitcode ("mov", "%s,_bp", spname);
2403 /* if use external stack but some variables were
2404 added to the local stack then decrement the
2406 if (options.useXstack && sym->stack)
2408 emitcode ("mov", "a,sp");
2409 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2410 emitcode ("mov", "sp,a");
2414 if ((IS_RENT (sym->etype) || options.stackAuto))
2416 if (options.useXstack)
2418 emitcode ("mov", "r0,%s", spname);
2419 emitcode ("movx", "a,@r0");
2420 emitcode ("mov", "_bp,a");
2421 emitcode ("dec", "%s", spname);
2425 emitcode ("pop", "_bp");
2429 /* restore the register bank */
2430 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2432 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2433 || !options.useXstack)
2435 /* Special case of ISR using non-zero bank with useXstack
2438 emitcode ("pop", "psw");
2442 if (IS_ISR (sym->etype))
2445 /* now we need to restore the registers */
2446 /* if this isr has no bank i.e. is going to
2447 run with bank 0 , then we need to save more
2449 if (!SPEC_BANK (sym->etype))
2451 /* if this function does not call any other
2452 function then we can be economical and
2453 save only those registers that are used */
2458 /* if any registers used */
2461 /* save the registers used */
2462 for (i = sym->regsUsed->size; i >= 0; i--)
2464 if (bitVectBitValue (sym->regsUsed, i) ||
2465 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2466 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2473 /* this function has a function call cannot
2474 determines register usage so we will have to pop the
2476 unsaveRBank (0, ic, FALSE);
2481 /* This ISR uses a non-zero bank.
2483 * Restore any register banks saved by genFunction
2486 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2489 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2491 if (savedBanks & (1 << ix))
2493 unsaveRBank(ix, NULL, FALSE);
2497 if (options.useXstack)
2499 /* Restore bank AFTER calling unsaveRBank,
2500 * since it can trash r0.
2502 emitcode ("pop", "psw");
2506 if (!inExcludeList ("dph"))
2507 emitcode ("pop", "dph");
2508 if (!inExcludeList ("dpl"))
2509 emitcode ("pop", "dpl");
2510 if (!inExcludeList ("b"))
2511 emitcode ("pop", "b");
2512 if (!inExcludeList ("acc"))
2513 emitcode ("pop", "acc");
2515 if (SPEC_CRTCL (sym->etype))
2516 emitcode ("setb", "ea");
2518 /* if debug then send end of function */
2519 /* if (options.debug && currFunc) */
2523 emitcode ("", "C$%s$%d$%d$%d ==.",
2524 FileBaseName (ic->filename), currFunc->lastLine,
2525 ic->level, ic->block);
2526 if (IS_STATIC (currFunc->etype))
2527 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2529 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2533 emitcode ("reti", "");
2537 if (SPEC_CRTCL (sym->etype))
2538 emitcode ("setb", "ea");
2540 if (sym->calleeSave)
2544 /* if any registers used */
2547 /* save the registers used */
2548 for (i = sym->regsUsed->size; i >= 0; i--)
2550 if (bitVectBitValue (sym->regsUsed, i) ||
2551 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2552 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2558 /* if debug then send end of function */
2562 emitcode ("", "C$%s$%d$%d$%d ==.",
2563 FileBaseName (ic->filename), currFunc->lastLine,
2564 ic->level, ic->block);
2565 if (IS_STATIC (currFunc->etype))
2566 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2568 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2572 emitcode ("ret", "");
2577 /*-----------------------------------------------------------------*/
2578 /* genRet - generate code for return statement */
2579 /*-----------------------------------------------------------------*/
2583 int size, offset = 0, pushed = 0;
2585 /* if we have no return value then
2586 just generate the "ret" */
2590 /* we have something to return then
2591 move the return value into place */
2592 aopOp (IC_LEFT (ic), ic, FALSE);
2593 size = AOP_SIZE (IC_LEFT (ic));
2598 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2601 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2603 emitcode ("push", "%s", l);
2608 l = aopGet (AOP (IC_LEFT (ic)), offset,
2610 if (strcmp (fReturn[offset], l))
2611 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2620 if (strcmp (fReturn[pushed], "a"))
2621 emitcode ("pop", fReturn[pushed]);
2623 emitcode ("pop", "acc");
2626 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2629 /* generate a jump to the return label
2630 if the next is not the return statement */
2631 if (!(ic->next && ic->next->op == LABEL &&
2632 IC_LABEL (ic->next) == returnLabel))
2634 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2638 /*-----------------------------------------------------------------*/
2639 /* genLabel - generates a label */
2640 /*-----------------------------------------------------------------*/
2642 genLabel (iCode * ic)
2644 /* special case never generate */
2645 if (IC_LABEL (ic) == entryLabel)
2648 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2651 /*-----------------------------------------------------------------*/
2652 /* genGoto - generates a ljmp */
2653 /*-----------------------------------------------------------------*/
2655 genGoto (iCode * ic)
2657 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2660 /*-----------------------------------------------------------------*/
2661 /* findLabelBackwards: walks back through the iCode chain looking */
2662 /* for the given label. Returns number of iCode instructions */
2663 /* between that label and given ic. */
2664 /* Returns zero if label not found. */
2665 /*-----------------------------------------------------------------*/
2667 findLabelBackwards (iCode * ic, int key)
2676 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2678 /* printf("findLabelBackwards = %d\n", count); */
2686 /*-----------------------------------------------------------------*/
2687 /* genPlusIncr :- does addition with increment if possible */
2688 /*-----------------------------------------------------------------*/
2690 genPlusIncr (iCode * ic)
2692 unsigned int icount;
2693 unsigned int size = getDataSize (IC_RESULT (ic));
2695 /* will try to generate an increment */
2696 /* if the right side is not a literal
2698 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2701 /* if the literal value of the right hand side
2702 is greater than 4 then it is not worth it */
2703 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2706 /* if increment 16 bits in register */
2707 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2715 /* If the next instruction is a goto and the goto target
2716 * is < 10 instructions previous to this, we can generate
2717 * jumps straight to that target.
2719 if (ic->next && ic->next->op == GOTO
2720 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2721 && labelRange <= 10)
2723 emitcode (";", "tail increment optimized");
2724 tlbl = IC_LABEL (ic->next);
2729 tlbl = newiTempLabel (NULL);
2732 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2733 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2734 IS_AOP_PREG (IC_RESULT (ic)))
2735 emitcode ("cjne", "%s,#0x00,%05d$"
2736 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2740 emitcode ("clr", "a");
2741 emitcode ("cjne", "a,%s,%05d$"
2742 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2746 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2749 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2750 IS_AOP_PREG (IC_RESULT (ic)))
2751 emitcode ("cjne", "%s,#0x00,%05d$"
2752 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2755 emitcode ("cjne", "a,%s,%05d$"
2756 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2759 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2763 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2764 IS_AOP_PREG (IC_RESULT (ic)))
2765 emitcode ("cjne", "%s,#0x00,%05d$"
2766 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2770 emitcode ("cjne", "a,%s,%05d$"
2771 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2774 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2779 emitcode ("", "%05d$:", tlbl->key + 100);
2784 /* if the sizes are greater than 1 then we cannot */
2785 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2786 AOP_SIZE (IC_LEFT (ic)) > 1)
2789 /* we can if the aops of the left & result match or
2790 if they are in registers and the registers are the
2792 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2797 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2798 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2799 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2805 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2814 /*-----------------------------------------------------------------*/
2815 /* outBitAcc - output a bit in acc */
2816 /*-----------------------------------------------------------------*/
2818 outBitAcc (operand * result)
2820 symbol *tlbl = newiTempLabel (NULL);
2821 /* if the result is a bit */
2822 if (AOP_TYPE (result) == AOP_CRY)
2824 aopPut (AOP (result), "a", 0);
2828 emitcode ("jz", "%05d$", tlbl->key + 100);
2829 emitcode ("mov", "a,%s", one);
2830 emitcode ("", "%05d$:", tlbl->key + 100);
2835 /*-----------------------------------------------------------------*/
2836 /* genPlusBits - generates code for addition of two bits */
2837 /*-----------------------------------------------------------------*/
2839 genPlusBits (iCode * ic)
2841 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2843 symbol *lbl = newiTempLabel (NULL);
2844 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2845 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2846 emitcode ("cpl", "c");
2847 emitcode ("", "%05d$:", (lbl->key + 100));
2848 outBitC (IC_RESULT (ic));
2852 emitcode ("clr", "a");
2853 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2854 emitcode ("rlc", "a");
2855 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2856 emitcode ("addc", "a,#0x00");
2857 outAcc (IC_RESULT (ic));
2862 /* This is the original version of this code.
2864 * This is being kept around for reference,
2865 * because I am not entirely sure I got it right...
2868 adjustArithmeticResult (iCode * ic)
2870 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2871 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2872 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2873 aopPut (AOP (IC_RESULT (ic)),
2874 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2877 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2878 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2879 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2880 aopPut (AOP (IC_RESULT (ic)),
2881 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2884 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2885 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2886 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2887 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2888 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2891 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2892 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2896 /* This is the pure and virtuous version of this code.
2897 * I'm pretty certain it's right, but not enough to toss the old
2901 adjustArithmeticResult (iCode * ic)
2903 if (opIsGptr (IC_RESULT (ic)) &&
2904 opIsGptr (IC_LEFT (ic)) &&
2905 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2907 aopPut (AOP (IC_RESULT (ic)),
2908 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2912 if (opIsGptr (IC_RESULT (ic)) &&
2913 opIsGptr (IC_RIGHT (ic)) &&
2914 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2916 aopPut (AOP (IC_RESULT (ic)),
2917 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2921 if (opIsGptr (IC_RESULT (ic)) &&
2922 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2923 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2924 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2925 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2928 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2929 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2934 /*-----------------------------------------------------------------*/
2935 /* genPlus - generates code for addition */
2936 /*-----------------------------------------------------------------*/
2938 genPlus (iCode * ic)
2940 int size, offset = 0;
2942 /* special cases :- */
2944 aopOp (IC_LEFT (ic), ic, FALSE);
2945 aopOp (IC_RIGHT (ic), ic, FALSE);
2946 aopOp (IC_RESULT (ic), ic, TRUE);
2948 /* if literal, literal on the right or
2949 if left requires ACC or right is already
2951 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2952 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2953 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2955 operand *t = IC_RIGHT (ic);
2956 IC_RIGHT (ic) = IC_LEFT (ic);
2960 /* if both left & right are in bit
2962 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2963 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2969 /* if left in bit space & right literal */
2970 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2971 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2973 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2974 /* if result in bit space */
2975 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2977 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2978 emitcode ("cpl", "c");
2979 outBitC (IC_RESULT (ic));
2983 size = getDataSize (IC_RESULT (ic));
2986 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2987 emitcode ("addc", "a,#00");
2988 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2994 /* if I can do an increment instead
2995 of add then GOOD for ME */
2996 if (genPlusIncr (ic) == TRUE)
2999 size = getDataSize (IC_RESULT (ic));
3003 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3005 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3007 emitcode ("add", "a,%s",
3008 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3010 emitcode ("addc", "a,%s",
3011 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3015 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3017 emitcode ("add", "a,%s",
3018 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3020 emitcode ("addc", "a,%s",
3021 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3023 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3026 adjustArithmeticResult (ic);
3029 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3030 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3031 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3034 /*-----------------------------------------------------------------*/
3035 /* genMinusDec :- does subtraction with deccrement if possible */
3036 /*-----------------------------------------------------------------*/
3038 genMinusDec (iCode * ic)
3040 unsigned int icount;
3041 unsigned int size = getDataSize (IC_RESULT (ic));
3043 /* will try to generate an increment */
3044 /* if the right side is not a literal
3046 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3049 /* if the literal value of the right hand side
3050 is greater than 4 then it is not worth it */
3051 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3054 /* if decrement 16 bits in register */
3055 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3063 /* If the next instruction is a goto and the goto target
3064 * is <= 10 instructions previous to this, we can generate
3065 * jumps straight to that target.
3067 if (ic->next && ic->next->op == GOTO
3068 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3069 && labelRange <= 10)
3071 emitcode (";", "tail decrement optimized");
3072 tlbl = IC_LABEL (ic->next);
3077 tlbl = newiTempLabel (NULL);
3081 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3082 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3083 IS_AOP_PREG (IC_RESULT (ic)))
3084 emitcode ("cjne", "%s,#0xff,%05d$"
3085 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3089 emitcode ("mov", "a,#0xff");
3090 emitcode ("cjne", "a,%s,%05d$"
3091 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3094 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3097 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3098 IS_AOP_PREG (IC_RESULT (ic)))
3099 emitcode ("cjne", "%s,#0xff,%05d$"
3100 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3104 emitcode ("cjne", "a,%s,%05d$"
3105 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3108 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3112 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3113 IS_AOP_PREG (IC_RESULT (ic)))
3114 emitcode ("cjne", "%s,#0xff,%05d$"
3115 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3119 emitcode ("cjne", "a,%s,%05d$"
3120 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3123 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3127 emitcode ("", "%05d$:", tlbl->key + 100);
3132 /* if the sizes are greater than 1 then we cannot */
3133 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3134 AOP_SIZE (IC_LEFT (ic)) > 1)
3137 /* we can if the aops of the left & result match or
3138 if they are in registers and the registers are the
3140 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3144 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3152 /*-----------------------------------------------------------------*/
3153 /* addSign - complete with sign */
3154 /*-----------------------------------------------------------------*/
3156 addSign (operand * result, int offset, int sign)
3158 int size = (getDataSize (result) - offset);
3163 emitcode ("rlc", "a");
3164 emitcode ("subb", "a,acc");
3166 aopPut (AOP (result), "a", offset++);
3170 aopPut (AOP (result), zero, offset++);
3174 /*-----------------------------------------------------------------*/
3175 /* genMinusBits - generates code for subtraction of two bits */
3176 /*-----------------------------------------------------------------*/
3178 genMinusBits (iCode * ic)
3180 symbol *lbl = newiTempLabel (NULL);
3181 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3183 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3184 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3185 emitcode ("cpl", "c");
3186 emitcode ("", "%05d$:", (lbl->key + 100));
3187 outBitC (IC_RESULT (ic));
3191 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3192 emitcode ("subb", "a,acc");
3193 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3194 emitcode ("inc", "a");
3195 emitcode ("", "%05d$:", (lbl->key + 100));
3196 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3197 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3201 /*-----------------------------------------------------------------*/
3202 /* genMinus - generates code for subtraction */
3203 /*-----------------------------------------------------------------*/
3205 genMinus (iCode * ic)
3207 int size, offset = 0;
3208 unsigned long lit = 0L;
3210 aopOp (IC_LEFT (ic), ic, FALSE);
3211 aopOp (IC_RIGHT (ic), ic, FALSE);
3212 aopOp (IC_RESULT (ic), ic, TRUE);
3214 /* special cases :- */
3215 /* if both left & right are in bit space */
3216 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3217 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3223 /* if I can do an decrement instead
3224 of subtract then GOOD for ME */
3225 if (genMinusDec (ic) == TRUE)
3228 size = getDataSize (IC_RESULT (ic));
3230 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3236 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3240 /* if literal, add a,#-lit, else normal subb */
3243 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3244 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3245 emitcode ("subb", "a,%s",
3246 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3249 /* first add without previous c */
3251 emitcode ("add", "a,#0x%02x",
3252 (unsigned int) (lit & 0x0FFL));
3254 emitcode ("addc", "a,#0x%02x",
3255 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3257 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3260 adjustArithmeticResult (ic);
3263 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3264 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3265 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3269 /*-----------------------------------------------------------------*/
3270 /* genMultbits :- multiplication of bits */
3271 /*-----------------------------------------------------------------*/
3273 genMultbits (operand * left,
3277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3278 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3283 /*-----------------------------------------------------------------*/
3284 /* genMultOneByte : 8*8=8/16 bit multiplication */
3285 /*-----------------------------------------------------------------*/
3287 genMultOneByte (operand * left,
3291 sym_link *opetype = operandType (result);
3293 int size=AOP_SIZE(result);
3295 //emitcode (";",__FUNCTION__);
3296 if (size<1 || size>2) {
3297 // this should never happen
3298 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3299 AOP_SIZE(result), __FILE__, lineno);
3303 /* (if two literals: the value is computed before) */
3304 /* if one literal, literal on the right */
3305 if (AOP_TYPE (left) == AOP_LIT)
3310 //emitcode (";", "swapped left and right");
3313 if (SPEC_USIGN(opetype)
3314 // ignore the sign of left and right, what else can we do?
3315 || (SPEC_USIGN(operandType(left)) &&
3316 SPEC_USIGN(operandType(right)))) {
3317 // just an unsigned 8*8=8/16 multiply
3318 //emitcode (";","unsigned");
3319 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3320 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3321 emitcode ("mul", "ab");
3322 aopPut (AOP (result), "a", 0);
3324 aopPut (AOP (result), "b", 1);
3329 // we have to do a signed multiply
3331 //emitcode (";", "signed");
3332 emitcode ("clr", "F0"); // reset sign flag
3333 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3334 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3336 lbl=newiTempLabel(NULL);
3337 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3338 // left side is negative, 8-bit two's complement, this fails for -128
3339 emitcode ("setb", "F0"); // set sign flag
3340 emitcode ("cpl", "a");
3341 emitcode ("inc", "a");
3343 emitcode ("", "%05d$:", lbl->key+100);
3344 emitcode ("xch", "a,b");
3347 if (AOP_TYPE(right)==AOP_LIT) {
3348 /* AND literal negative */
3349 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3350 // two's complement for literal<0
3351 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3352 emitcode ("cpl", "a");
3353 emitcode ("inc", "a");
3356 lbl=newiTempLabel(NULL);
3357 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3358 // right side is negative, 8-bit two's complement
3359 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3360 emitcode ("cpl", "a");
3361 emitcode ("inc", "a");
3362 emitcode ("", "%05d$:", lbl->key+100);
3364 emitcode ("mul", "ab");
3366 lbl=newiTempLabel(NULL);
3367 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3368 // only ONE op was negative, we have to do a 8/16-bit two's complement
3369 emitcode ("cpl", "a"); // lsb
3371 emitcode ("inc", "a");
3373 emitcode ("add", "a,#1");
3374 emitcode ("xch", "a,b");
3375 emitcode ("cpl", "a"); // msb
3376 emitcode ("addc", "a,#0");
3377 emitcode ("xch", "a,b");
3380 emitcode ("", "%05d$:", lbl->key+100);
3381 aopPut (AOP (result), "a", 0);
3383 aopPut (AOP (result), "b", 1);
3387 /*-----------------------------------------------------------------*/
3388 /* genMult - generates code for multiplication */
3389 /*-----------------------------------------------------------------*/
3391 genMult (iCode * ic)
3393 operand *left = IC_LEFT (ic);
3394 operand *right = IC_RIGHT (ic);
3395 operand *result = IC_RESULT (ic);
3397 /* assign the amsops */
3398 aopOp (left, ic, FALSE);
3399 aopOp (right, ic, FALSE);
3400 aopOp (result, ic, TRUE);
3402 /* special cases first */
3404 if (AOP_TYPE (left) == AOP_CRY &&
3405 AOP_TYPE (right) == AOP_CRY)
3407 genMultbits (left, right, result);
3411 /* if both are of size == 1 */
3412 if (AOP_SIZE (left) == 1 &&
3413 AOP_SIZE (right) == 1)
3415 genMultOneByte (left, right, result);
3419 /* should have been converted to function call */
3423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3424 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3425 freeAsmop (result, NULL, ic, TRUE);
3428 /*-----------------------------------------------------------------*/
3429 /* genDivbits :- division of bits */
3430 /*-----------------------------------------------------------------*/
3432 genDivbits (operand * left,
3439 /* the result must be bit */
3440 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3441 l = aopGet (AOP (left), 0, FALSE, FALSE);
3445 emitcode ("div", "ab");
3446 emitcode ("rrc", "a");
3447 aopPut (AOP (result), "c", 0);
3450 /*-----------------------------------------------------------------*/
3451 /* genDivOneByte : 8 bit division */
3452 /*-----------------------------------------------------------------*/
3454 genDivOneByte (operand * left,
3458 sym_link *opetype = operandType (result);
3463 size = AOP_SIZE (result) - 1;
3465 /* signed or unsigned */
3466 if (SPEC_USIGN (opetype))
3468 /* unsigned is easy */
3469 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3470 l = aopGet (AOP (left), 0, FALSE, FALSE);
3472 emitcode ("div", "ab");
3473 aopPut (AOP (result), "a", 0);
3475 aopPut (AOP (result), zero, offset++);
3479 /* signed is a little bit more difficult */
3481 /* save the signs of the operands */
3482 l = aopGet (AOP (left), 0, FALSE, FALSE);
3484 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3485 emitcode ("push", "acc"); /* save it on the stack */
3487 /* now sign adjust for both left & right */
3488 l = aopGet (AOP (right), 0, FALSE, FALSE);
3490 lbl = newiTempLabel (NULL);
3491 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3492 emitcode ("cpl", "a");
3493 emitcode ("inc", "a");
3494 emitcode ("", "%05d$:", (lbl->key + 100));
3495 emitcode ("mov", "b,a");
3497 /* sign adjust left side */
3498 l = aopGet (AOP (left), 0, FALSE, FALSE);
3501 lbl = newiTempLabel (NULL);
3502 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3503 emitcode ("cpl", "a");
3504 emitcode ("inc", "a");
3505 emitcode ("", "%05d$:", (lbl->key + 100));
3507 /* now the division */
3508 emitcode ("div", "ab");
3509 /* we are interested in the lower order
3511 emitcode ("mov", "b,a");
3512 lbl = newiTempLabel (NULL);
3513 emitcode ("pop", "acc");
3514 /* if there was an over flow we don't
3515 adjust the sign of the result */
3516 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3517 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3519 emitcode ("clr", "a");
3520 emitcode ("subb", "a,b");
3521 emitcode ("mov", "b,a");
3522 emitcode ("", "%05d$:", (lbl->key + 100));
3524 /* now we are done */
3525 aopPut (AOP (result), "b", 0);
3528 emitcode ("mov", "c,b.7");
3529 emitcode ("subb", "a,acc");
3532 aopPut (AOP (result), "a", offset++);
3536 /*-----------------------------------------------------------------*/
3537 /* genDiv - generates code for division */
3538 /*-----------------------------------------------------------------*/
3542 operand *left = IC_LEFT (ic);
3543 operand *right = IC_RIGHT (ic);
3544 operand *result = IC_RESULT (ic);
3546 /* assign the amsops */
3547 aopOp (left, ic, FALSE);
3548 aopOp (right, ic, FALSE);
3549 aopOp (result, ic, TRUE);
3551 /* special cases first */
3553 if (AOP_TYPE (left) == AOP_CRY &&
3554 AOP_TYPE (right) == AOP_CRY)
3556 genDivbits (left, right, result);
3560 /* if both are of size == 1 */
3561 if (AOP_SIZE (left) == 1 &&
3562 AOP_SIZE (right) == 1)
3564 genDivOneByte (left, right, result);
3568 /* should have been converted to function call */
3571 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3572 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3573 freeAsmop (result, NULL, ic, TRUE);
3576 /*-----------------------------------------------------------------*/
3577 /* genModbits :- modulus of bits */
3578 /*-----------------------------------------------------------------*/
3580 genModbits (operand * left,
3587 /* the result must be bit */
3588 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3589 l = aopGet (AOP (left), 0, FALSE, FALSE);
3593 emitcode ("div", "ab");
3594 emitcode ("mov", "a,b");
3595 emitcode ("rrc", "a");
3596 aopPut (AOP (result), "c", 0);
3599 /*-----------------------------------------------------------------*/
3600 /* genModOneByte : 8 bit modulus */
3601 /*-----------------------------------------------------------------*/
3603 genModOneByte (operand * left,
3607 sym_link *opetype = operandType (result);
3611 /* signed or unsigned */
3612 if (SPEC_USIGN (opetype))
3614 /* unsigned is easy */
3615 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3616 l = aopGet (AOP (left), 0, FALSE, FALSE);
3618 emitcode ("div", "ab");
3619 aopPut (AOP (result), "b", 0);
3623 /* signed is a little bit more difficult */
3625 /* save the signs of the operands */
3626 l = aopGet (AOP (left), 0, FALSE, FALSE);
3629 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3630 emitcode ("push", "acc"); /* save it on the stack */
3632 /* now sign adjust for both left & right */
3633 l = aopGet (AOP (right), 0, FALSE, FALSE);
3636 lbl = newiTempLabel (NULL);
3637 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3638 emitcode ("cpl", "a");
3639 emitcode ("inc", "a");
3640 emitcode ("", "%05d$:", (lbl->key + 100));
3641 emitcode ("mov", "b,a");
3643 /* sign adjust left side */
3644 l = aopGet (AOP (left), 0, FALSE, FALSE);
3647 lbl = newiTempLabel (NULL);
3648 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3649 emitcode ("cpl", "a");
3650 emitcode ("inc", "a");
3651 emitcode ("", "%05d$:", (lbl->key + 100));
3653 /* now the multiplication */
3654 emitcode ("div", "ab");
3655 /* we are interested in the lower order
3657 lbl = newiTempLabel (NULL);
3658 emitcode ("pop", "acc");
3659 /* if there was an over flow we don't
3660 adjust the sign of the result */
3661 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3662 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3664 emitcode ("clr", "a");
3665 emitcode ("subb", "a,b");
3666 emitcode ("mov", "b,a");
3667 emitcode ("", "%05d$:", (lbl->key + 100));
3669 /* now we are done */
3670 aopPut (AOP (result), "b", 0);
3674 /*-----------------------------------------------------------------*/
3675 /* genMod - generates code for division */
3676 /*-----------------------------------------------------------------*/
3680 operand *left = IC_LEFT (ic);
3681 operand *right = IC_RIGHT (ic);
3682 operand *result = IC_RESULT (ic);
3684 /* assign the amsops */
3685 aopOp (left, ic, FALSE);
3686 aopOp (right, ic, FALSE);
3687 aopOp (result, ic, TRUE);
3689 /* special cases first */
3691 if (AOP_TYPE (left) == AOP_CRY &&
3692 AOP_TYPE (right) == AOP_CRY)
3694 genModbits (left, right, result);
3698 /* if both are of size == 1 */
3699 if (AOP_SIZE (left) == 1 &&
3700 AOP_SIZE (right) == 1)
3702 genModOneByte (left, right, result);
3706 /* should have been converted to function call */
3710 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3711 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3712 freeAsmop (result, NULL, ic, TRUE);
3715 /*-----------------------------------------------------------------*/
3716 /* genIfxJump :- will create a jump depending on the ifx */
3717 /*-----------------------------------------------------------------*/
3719 genIfxJump (iCode * ic, char *jval)
3722 symbol *tlbl = newiTempLabel (NULL);
3725 /* if true label then we jump if condition
3729 jlbl = IC_TRUE (ic);
3730 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3731 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3735 /* false label is present */
3736 jlbl = IC_FALSE (ic);
3737 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3738 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3740 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3741 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3743 emitcode (inst, "%05d$", tlbl->key + 100);
3744 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3745 emitcode ("", "%05d$:", tlbl->key + 100);
3747 /* mark the icode as generated */
3751 /*-----------------------------------------------------------------*/
3752 /* genCmp :- greater or less than comparison */
3753 /*-----------------------------------------------------------------*/
3755 genCmp (operand * left, operand * right,
3756 operand * result, iCode * ifx, int sign, iCode *ic)
3758 int size, offset = 0;
3759 unsigned long lit = 0L;
3761 /* if left & right are bit variables */
3762 if (AOP_TYPE (left) == AOP_CRY &&
3763 AOP_TYPE (right) == AOP_CRY)
3765 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3766 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3770 /* subtract right from left if at the
3771 end the carry flag is set then we know that
3772 left is greater than right */
3773 size = max (AOP_SIZE (left), AOP_SIZE (right));
3775 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3776 if ((size == 1) && !sign &&
3777 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3779 symbol *lbl = newiTempLabel (NULL);
3780 emitcode ("cjne", "%s,%s,%05d$",
3781 aopGet (AOP (left), offset, FALSE, FALSE),
3782 aopGet (AOP (right), offset, FALSE, FALSE),
3784 emitcode ("", "%05d$:", lbl->key + 100);
3788 if (AOP_TYPE (right) == AOP_LIT)
3790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3791 /* optimize if(x < 0) or if(x >= 0) */
3800 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3801 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3803 genIfxJump (ifx, "acc.7");
3807 emitcode ("rlc", "a");
3815 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3816 if (sign && size == 0)
3818 emitcode ("xrl", "a,#0x80");
3819 if (AOP_TYPE (right) == AOP_LIT)
3821 unsigned long lit = (unsigned long)
3822 floatFromVal (AOP (right)->aopu.aop_lit);
3823 emitcode ("subb", "a,#0x%02x",
3824 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3828 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3829 emitcode ("xrl", "b,#0x80");
3830 emitcode ("subb", "a,b");
3834 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3840 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3841 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3842 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3848 /* if the result is used in the next
3849 ifx conditional branch then generate
3850 code a little differently */
3852 genIfxJump (ifx, "c");
3855 /* leave the result in acc */
3859 /*-----------------------------------------------------------------*/
3860 /* genCmpGt :- greater than comparison */
3861 /*-----------------------------------------------------------------*/
3863 genCmpGt (iCode * ic, iCode * ifx)
3865 operand *left, *right, *result;
3866 sym_link *letype, *retype;
3869 left = IC_LEFT (ic);
3870 right = IC_RIGHT (ic);
3871 result = IC_RESULT (ic);
3873 letype = getSpec (operandType (left));
3874 retype = getSpec (operandType (right));
3875 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3876 /* assign the amsops */
3877 aopOp (left, ic, FALSE);
3878 aopOp (right, ic, FALSE);
3879 aopOp (result, ic, TRUE);
3881 genCmp (right, left, result, ifx, sign,ic);
3883 freeAsmop (result, NULL, ic, TRUE);
3886 /*-----------------------------------------------------------------*/
3887 /* genCmpLt - less than comparisons */
3888 /*-----------------------------------------------------------------*/
3890 genCmpLt (iCode * ic, iCode * ifx)
3892 operand *left, *right, *result;
3893 sym_link *letype, *retype;
3896 left = IC_LEFT (ic);
3897 right = IC_RIGHT (ic);
3898 result = IC_RESULT (ic);
3900 letype = getSpec (operandType (left));
3901 retype = getSpec (operandType (right));
3902 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3904 /* assign the amsops */
3905 aopOp (left, ic, FALSE);
3906 aopOp (right, ic, FALSE);
3907 aopOp (result, ic, TRUE);
3909 genCmp (left, right, result, ifx, sign,ic);
3911 freeAsmop (result, NULL, ic, TRUE);
3914 /*-----------------------------------------------------------------*/
3915 /* gencjneshort - compare and jump if not equal */
3916 /*-----------------------------------------------------------------*/
3918 gencjneshort (operand * left, operand * right, symbol * lbl)
3920 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3922 unsigned long lit = 0L;
3924 /* if the left side is a literal or
3925 if the right is in a pointer register and left
3927 if ((AOP_TYPE (left) == AOP_LIT) ||
3928 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3934 if (AOP_TYPE (right) == AOP_LIT)
3935 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3937 /* if the right side is a literal then anything goes */
3938 if (AOP_TYPE (right) == AOP_LIT &&
3939 AOP_TYPE (left) != AOP_DIR)
3943 emitcode ("cjne", "%s,%s,%05d$",
3944 aopGet (AOP (left), offset, FALSE, FALSE),
3945 aopGet (AOP (right), offset, FALSE, FALSE),
3951 /* if the right side is in a register or in direct space or
3952 if the left is a pointer register & right is not */
3953 else if (AOP_TYPE (right) == AOP_REG ||
3954 AOP_TYPE (right) == AOP_DIR ||
3955 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3956 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3960 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3961 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3962 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3963 emitcode ("jnz", "%05d$", lbl->key + 100);
3965 emitcode ("cjne", "a,%s,%05d$",
3966 aopGet (AOP (right), offset, FALSE, TRUE),
3973 /* right is a pointer reg need both a & b */
3976 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3977 if (strcmp (l, "b"))
3978 emitcode ("mov", "b,%s", l);
3979 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3980 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3986 /*-----------------------------------------------------------------*/
3987 /* gencjne - compare and jump if not equal */
3988 /*-----------------------------------------------------------------*/
3990 gencjne (operand * left, operand * right, symbol * lbl)
3992 symbol *tlbl = newiTempLabel (NULL);
3994 gencjneshort (left, right, lbl);
3996 emitcode ("mov", "a,%s", one);
3997 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3998 emitcode ("", "%05d$:", lbl->key + 100);
3999 emitcode ("clr", "a");
4000 emitcode ("", "%05d$:", tlbl->key + 100);
4003 /*-----------------------------------------------------------------*/
4004 /* genCmpEq - generates code for equal to */
4005 /*-----------------------------------------------------------------*/
4007 genCmpEq (iCode * ic, iCode * ifx)
4009 operand *left, *right, *result;
4011 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4012 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4013 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4015 /* if literal, literal on the right or
4016 if the right is in a pointer register and left
4018 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4019 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4021 operand *t = IC_RIGHT (ic);
4022 IC_RIGHT (ic) = IC_LEFT (ic);
4026 if (ifx && !AOP_SIZE (result))
4029 /* if they are both bit variables */
4030 if (AOP_TYPE (left) == AOP_CRY &&
4031 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4033 if (AOP_TYPE (right) == AOP_LIT)
4035 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4039 emitcode ("cpl", "c");
4043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4047 emitcode ("clr", "c");
4049 /* AOP_TYPE(right) == AOP_CRY */
4053 symbol *lbl = newiTempLabel (NULL);
4054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4055 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4056 emitcode ("cpl", "c");
4057 emitcode ("", "%05d$:", (lbl->key + 100));
4059 /* if true label then we jump if condition
4061 tlbl = newiTempLabel (NULL);
4064 emitcode ("jnc", "%05d$", tlbl->key + 100);
4065 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4069 emitcode ("jc", "%05d$", tlbl->key + 100);
4070 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4072 emitcode ("", "%05d$:", tlbl->key + 100);
4076 tlbl = newiTempLabel (NULL);
4077 gencjneshort (left, right, tlbl);
4080 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4081 emitcode ("", "%05d$:", tlbl->key + 100);
4085 symbol *lbl = newiTempLabel (NULL);
4086 emitcode ("sjmp", "%05d$", lbl->key + 100);
4087 emitcode ("", "%05d$:", tlbl->key + 100);
4088 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4089 emitcode ("", "%05d$:", lbl->key + 100);
4092 /* mark the icode as generated */
4097 /* if they are both bit variables */
4098 if (AOP_TYPE (left) == AOP_CRY &&
4099 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4101 if (AOP_TYPE (right) == AOP_LIT)
4103 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4106 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4107 emitcode ("cpl", "c");
4111 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4115 emitcode ("clr", "c");
4117 /* AOP_TYPE(right) == AOP_CRY */
4121 symbol *lbl = newiTempLabel (NULL);
4122 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4123 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4124 emitcode ("cpl", "c");
4125 emitcode ("", "%05d$:", (lbl->key + 100));
4128 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4135 genIfxJump (ifx, "c");
4138 /* if the result is used in an arithmetic operation
4139 then put the result in place */
4144 gencjne (left, right, newiTempLabel (NULL));
4145 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4147 aopPut (AOP (result), "a", 0);
4152 genIfxJump (ifx, "a");
4155 /* if the result is used in an arithmetic operation
4156 then put the result in place */
4157 if (AOP_TYPE (result) != AOP_CRY)
4159 /* leave the result in acc */
4163 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4164 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4165 freeAsmop (result, NULL, ic, TRUE);
4168 /*-----------------------------------------------------------------*/
4169 /* ifxForOp - returns the icode containing the ifx for operand */
4170 /*-----------------------------------------------------------------*/
4172 ifxForOp (operand * op, iCode * ic)
4174 /* if true symbol then needs to be assigned */
4175 if (IS_TRUE_SYMOP (op))
4178 /* if this has register type condition and
4179 the next instruction is ifx with the same operand
4180 and live to of the operand is upto the ifx only then */
4182 ic->next->op == IFX &&
4183 IC_COND (ic->next)->key == op->key &&
4184 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4190 /*-----------------------------------------------------------------*/
4191 /* hasInc - operand is incremented before any other use */
4192 /*-----------------------------------------------------------------*/
4194 hasInc (operand *op, iCode *ic)
4196 sym_link *type = operandType(op);
4197 sym_link *retype = getSpec (type);
4198 iCode *lic = ic->next;
4201 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4202 isize = getSize(type->next);
4204 /* if operand of the form op = op + <sizeof *op> */
4205 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4206 isOperandEqual(IC_RESULT(lic),op) &&
4207 isOperandLiteral(IC_RIGHT(lic)) &&
4208 operandLitValue(IC_RIGHT(lic)) == isize) {
4211 /* if the operand used or deffed */
4212 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4220 /*-----------------------------------------------------------------*/
4221 /* genAndOp - for && operation */
4222 /*-----------------------------------------------------------------*/
4224 genAndOp (iCode * ic)
4226 operand *left, *right, *result;
4229 /* note here that && operations that are in an
4230 if statement are taken away by backPatchLabels
4231 only those used in arthmetic operations remain */
4232 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4233 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4234 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4236 /* if both are bit variables */
4237 if (AOP_TYPE (left) == AOP_CRY &&
4238 AOP_TYPE (right) == AOP_CRY)
4240 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4241 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4246 tlbl = newiTempLabel (NULL);
4248 emitcode ("jz", "%05d$", tlbl->key + 100);
4250 emitcode ("", "%05d$:", tlbl->key + 100);
4254 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4255 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4256 freeAsmop (result, NULL, ic, TRUE);
4260 /*-----------------------------------------------------------------*/
4261 /* genOrOp - for || operation */
4262 /*-----------------------------------------------------------------*/
4264 genOrOp (iCode * ic)
4266 operand *left, *right, *result;
4269 /* note here that || operations that are in an
4270 if statement are taken away by backPatchLabels
4271 only those used in arthmetic operations remain */
4272 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4273 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4274 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4276 /* if both are bit variables */
4277 if (AOP_TYPE (left) == AOP_CRY &&
4278 AOP_TYPE (right) == AOP_CRY)
4280 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4281 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4286 tlbl = newiTempLabel (NULL);
4288 emitcode ("jnz", "%05d$", tlbl->key + 100);
4290 emitcode ("", "%05d$:", tlbl->key + 100);
4294 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4295 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4296 freeAsmop (result, NULL, ic, TRUE);
4299 /*-----------------------------------------------------------------*/
4300 /* isLiteralBit - test if lit == 2^n */
4301 /*-----------------------------------------------------------------*/
4303 isLiteralBit (unsigned long lit)
4305 unsigned long pw[32] =
4306 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4307 0x100L, 0x200L, 0x400L, 0x800L,
4308 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4309 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4310 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4311 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4312 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4315 for (idx = 0; idx < 32; idx++)
4321 /*-----------------------------------------------------------------*/
4322 /* continueIfTrue - */
4323 /*-----------------------------------------------------------------*/
4325 continueIfTrue (iCode * ic)
4328 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4332 /*-----------------------------------------------------------------*/
4334 /*-----------------------------------------------------------------*/
4336 jumpIfTrue (iCode * ic)
4339 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4343 /*-----------------------------------------------------------------*/
4344 /* jmpTrueOrFalse - */
4345 /*-----------------------------------------------------------------*/
4347 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4349 // ugly but optimized by peephole
4352 symbol *nlbl = newiTempLabel (NULL);
4353 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4354 emitcode ("", "%05d$:", tlbl->key + 100);
4355 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4356 emitcode ("", "%05d$:", nlbl->key + 100);
4360 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4361 emitcode ("", "%05d$:", tlbl->key + 100);
4366 /*-----------------------------------------------------------------*/
4367 /* genAnd - code for and */
4368 /*-----------------------------------------------------------------*/
4370 genAnd (iCode * ic, iCode * ifx)
4372 operand *left, *right, *result;
4373 int size, offset = 0;
4374 unsigned long lit = 0L;
4378 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4379 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4380 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4383 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4385 AOP_TYPE (left), AOP_TYPE (right));
4386 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4388 AOP_SIZE (left), AOP_SIZE (right));
4391 /* if left is a literal & right is not then exchange them */
4392 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4393 AOP_NEEDSACC (left))
4395 operand *tmp = right;
4400 /* if result = right then exchange them */
4401 if (sameRegs (AOP (result), AOP (right)))
4403 operand *tmp = right;
4408 /* if right is bit then exchange them */
4409 if (AOP_TYPE (right) == AOP_CRY &&
4410 AOP_TYPE (left) != AOP_CRY)
4412 operand *tmp = right;
4416 if (AOP_TYPE (right) == AOP_LIT)
4417 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4419 size = AOP_SIZE (result);
4422 // result = bit & yy;
4423 if (AOP_TYPE (left) == AOP_CRY)
4425 // c = bit & literal;
4426 if (AOP_TYPE (right) == AOP_LIT)
4430 if (size && sameRegs (AOP (result), AOP (left)))
4433 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4438 if (size && (AOP_TYPE (result) == AOP_CRY))
4440 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4443 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4448 emitcode ("clr", "c");
4453 if (AOP_TYPE (right) == AOP_CRY)
4456 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4457 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4462 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4464 emitcode ("rrc", "a");
4465 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4473 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4474 genIfxJump (ifx, "c");
4478 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4479 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4480 if ((AOP_TYPE (right) == AOP_LIT) &&
4481 (AOP_TYPE (result) == AOP_CRY) &&
4482 (AOP_TYPE (left) != AOP_CRY))
4484 int posbit = isLiteralBit (lit);
4489 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4492 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4498 sprintf (buffer, "acc.%d", posbit & 0x07);
4499 genIfxJump (ifx, buffer);
4506 symbol *tlbl = newiTempLabel (NULL);
4507 int sizel = AOP_SIZE (left);
4509 emitcode ("setb", "c");
4512 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4514 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4516 if ((posbit = isLiteralBit (bytelit)) != 0)
4517 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4520 if (bytelit != 0x0FFL)
4521 emitcode ("anl", "a,%s",
4522 aopGet (AOP (right), offset, FALSE, TRUE));
4523 emitcode ("jnz", "%05d$", tlbl->key + 100);
4528 // bit = left & literal
4531 emitcode ("clr", "c");
4532 emitcode ("", "%05d$:", tlbl->key + 100);
4534 // if(left & literal)
4538 jmpTrueOrFalse (ifx, tlbl);
4546 /* if left is same as result */
4547 if (sameRegs (AOP (result), AOP (left)))
4549 for (; size--; offset++)
4551 if (AOP_TYPE (right) == AOP_LIT)
4553 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4555 else if (bytelit == 0)
4556 aopPut (AOP (result), zero, offset);
4557 else if (IS_AOP_PREG (result))
4559 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4560 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4561 aopPut (AOP (result), "a", offset);
4564 emitcode ("anl", "%s,%s",
4565 aopGet (AOP (left), offset, FALSE, TRUE),
4566 aopGet (AOP (right), offset, FALSE, FALSE));
4570 if (AOP_TYPE (left) == AOP_ACC)
4571 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4574 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4575 if (IS_AOP_PREG (result))
4577 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4578 aopPut (AOP (result), "a", offset);
4582 emitcode ("anl", "%s,a",
4583 aopGet (AOP (left), offset, FALSE, TRUE));
4590 // left & result in different registers
4591 if (AOP_TYPE (result) == AOP_CRY)
4594 // if(size), result in bit
4595 // if(!size && ifx), conditional oper: if(left & right)
4596 symbol *tlbl = newiTempLabel (NULL);
4597 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4599 emitcode ("setb", "c");
4602 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4603 emitcode ("anl", "a,%s",
4604 aopGet (AOP (left), offset, FALSE, FALSE));
4605 emitcode ("jnz", "%05d$", tlbl->key + 100);
4611 emitcode ("", "%05d$:", tlbl->key + 100);
4615 jmpTrueOrFalse (ifx, tlbl);
4619 for (; (size--); offset++)
4622 // result = left & right
4623 if (AOP_TYPE (right) == AOP_LIT)
4625 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4627 aopPut (AOP (result),
4628 aopGet (AOP (left), offset, FALSE, FALSE),
4632 else if (bytelit == 0)
4634 aopPut (AOP (result), zero, offset);
4638 // faster than result <- left, anl result,right
4639 // and better if result is SFR
4640 if (AOP_TYPE (left) == AOP_ACC)
4641 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4645 emitcode ("anl", "a,%s",
4646 aopGet (AOP (left), offset, FALSE, FALSE));
4648 aopPut (AOP (result), "a", offset);
4654 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4655 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4656 freeAsmop (result, NULL, ic, TRUE);
4659 /*-----------------------------------------------------------------*/
4660 /* genOr - code for or */
4661 /*-----------------------------------------------------------------*/
4663 genOr (iCode * ic, iCode * ifx)
4665 operand *left, *right, *result;
4666 int size, offset = 0;
4667 unsigned long lit = 0L;
4669 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4670 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4671 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4674 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4676 AOP_TYPE (left), AOP_TYPE (right));
4677 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4679 AOP_SIZE (left), AOP_SIZE (right));
4682 /* if left is a literal & right is not then exchange them */
4683 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4684 AOP_NEEDSACC (left))
4686 operand *tmp = right;
4691 /* if result = right then exchange them */
4692 if (sameRegs (AOP (result), AOP (right)))
4694 operand *tmp = right;
4699 /* if right is bit then exchange them */
4700 if (AOP_TYPE (right) == AOP_CRY &&
4701 AOP_TYPE (left) != AOP_CRY)
4703 operand *tmp = right;
4707 if (AOP_TYPE (right) == AOP_LIT)
4708 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4710 size = AOP_SIZE (result);
4714 if (AOP_TYPE (left) == AOP_CRY)
4716 if (AOP_TYPE (right) == AOP_LIT)
4718 // c = bit & literal;
4721 // lit != 0 => result = 1
4722 if (AOP_TYPE (result) == AOP_CRY)
4725 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4727 continueIfTrue (ifx);
4730 emitcode ("setb", "c");
4734 // lit == 0 => result = left
4735 if (size && sameRegs (AOP (result), AOP (left)))
4737 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4742 if (AOP_TYPE (right) == AOP_CRY)
4745 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4746 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4751 symbol *tlbl = newiTempLabel (NULL);
4752 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4753 emitcode ("setb", "c");
4754 emitcode ("jb", "%s,%05d$",
4755 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4757 emitcode ("jnz", "%05d$", tlbl->key + 100);
4758 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4760 jmpTrueOrFalse (ifx, tlbl);
4766 emitcode ("", "%05d$:", tlbl->key + 100);
4775 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4776 genIfxJump (ifx, "c");
4780 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4781 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4782 if ((AOP_TYPE (right) == AOP_LIT) &&
4783 (AOP_TYPE (result) == AOP_CRY) &&
4784 (AOP_TYPE (left) != AOP_CRY))
4790 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4792 continueIfTrue (ifx);
4797 // lit = 0, result = boolean(left)
4799 emitcode ("setb", "c");
4803 symbol *tlbl = newiTempLabel (NULL);
4804 emitcode ("jnz", "%05d$", tlbl->key + 100);
4806 emitcode ("", "%05d$:", tlbl->key + 100);
4810 genIfxJump (ifx, "a");
4818 /* if left is same as result */
4819 if (sameRegs (AOP (result), AOP (left)))
4821 for (; size--; offset++)
4823 if (AOP_TYPE (right) == AOP_LIT)
4825 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4827 else if (IS_AOP_PREG (left))
4829 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4830 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4831 aopPut (AOP (result), "a", offset);
4834 emitcode ("orl", "%s,%s",
4835 aopGet (AOP (left), offset, FALSE, TRUE),
4836 aopGet (AOP (right), offset, FALSE, FALSE));
4840 if (AOP_TYPE (left) == AOP_ACC)
4841 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4844 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4845 if (IS_AOP_PREG (left))
4847 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4848 aopPut (AOP (result), "a", offset);
4851 emitcode ("orl", "%s,a",
4852 aopGet (AOP (left), offset, FALSE, TRUE));
4859 // left & result in different registers
4860 if (AOP_TYPE (result) == AOP_CRY)
4863 // if(size), result in bit
4864 // if(!size && ifx), conditional oper: if(left | right)
4865 symbol *tlbl = newiTempLabel (NULL);
4866 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4868 emitcode ("setb", "c");
4871 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4872 emitcode ("orl", "a,%s",
4873 aopGet (AOP (left), offset, FALSE, FALSE));
4874 emitcode ("jnz", "%05d$", tlbl->key + 100);
4880 emitcode ("", "%05d$:", tlbl->key + 100);
4884 jmpTrueOrFalse (ifx, tlbl);
4887 for (; (size--); offset++)
4890 // result = left & right
4891 if (AOP_TYPE (right) == AOP_LIT)
4893 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4895 aopPut (AOP (result),
4896 aopGet (AOP (left), offset, FALSE, FALSE),
4901 // faster than result <- left, anl result,right
4902 // and better if result is SFR
4903 if (AOP_TYPE (left) == AOP_ACC)
4904 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4908 emitcode ("orl", "a,%s",
4909 aopGet (AOP (left), offset, FALSE, FALSE));
4911 aopPut (AOP (result), "a", offset);
4916 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4917 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4918 freeAsmop (result, NULL, ic, TRUE);
4921 /*-----------------------------------------------------------------*/
4922 /* genXor - code for xclusive or */
4923 /*-----------------------------------------------------------------*/
4925 genXor (iCode * ic, iCode * ifx)
4927 operand *left, *right, *result;
4928 int size, offset = 0;
4929 unsigned long lit = 0L;
4931 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4932 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4933 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4936 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4938 AOP_TYPE (left), AOP_TYPE (right));
4939 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4941 AOP_SIZE (left), AOP_SIZE (right));
4944 /* if left is a literal & right is not ||
4945 if left needs acc & right does not */
4946 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4947 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4949 operand *tmp = right;
4954 /* if result = right then exchange them */
4955 if (sameRegs (AOP (result), AOP (right)))
4957 operand *tmp = right;
4962 /* if right is bit then exchange them */
4963 if (AOP_TYPE (right) == AOP_CRY &&
4964 AOP_TYPE (left) != AOP_CRY)
4966 operand *tmp = right;
4970 if (AOP_TYPE (right) == AOP_LIT)
4971 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4973 size = AOP_SIZE (result);
4977 if (AOP_TYPE (left) == AOP_CRY)
4979 if (AOP_TYPE (right) == AOP_LIT)
4981 // c = bit & literal;
4984 // lit>>1 != 0 => result = 1
4985 if (AOP_TYPE (result) == AOP_CRY)
4988 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4990 continueIfTrue (ifx);
4993 emitcode ("setb", "c");
5000 // lit == 0, result = left
5001 if (size && sameRegs (AOP (result), AOP (left)))
5003 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5007 // lit == 1, result = not(left)
5008 if (size && sameRegs (AOP (result), AOP (left)))
5010 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5015 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5016 emitcode ("cpl", "c");
5025 symbol *tlbl = newiTempLabel (NULL);
5026 if (AOP_TYPE (right) == AOP_CRY)
5029 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5033 int sizer = AOP_SIZE (right);
5035 // if val>>1 != 0, result = 1
5036 emitcode ("setb", "c");
5039 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5041 // test the msb of the lsb
5042 emitcode ("anl", "a,#0xfe");
5043 emitcode ("jnz", "%05d$", tlbl->key + 100);
5047 emitcode ("rrc", "a");
5049 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5050 emitcode ("cpl", "c");
5051 emitcode ("", "%05d$:", (tlbl->key + 100));
5058 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5059 genIfxJump (ifx, "c");
5063 if (sameRegs (AOP (result), AOP (left)))
5065 /* if left is same as result */
5066 for (; size--; offset++)
5068 if (AOP_TYPE (right) == AOP_LIT)
5070 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5072 else if (IS_AOP_PREG (left))
5074 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5075 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5076 aopPut (AOP (result), "a", offset);
5079 emitcode ("xrl", "%s,%s",
5080 aopGet (AOP (left), offset, FALSE, TRUE),
5081 aopGet (AOP (right), offset, FALSE, FALSE));
5085 if (AOP_TYPE (left) == AOP_ACC)
5086 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5089 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5090 if (IS_AOP_PREG (left))
5092 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5093 aopPut (AOP (result), "a", offset);
5096 emitcode ("xrl", "%s,a",
5097 aopGet (AOP (left), offset, FALSE, TRUE));
5104 // left & result in different registers
5105 if (AOP_TYPE (result) == AOP_CRY)
5108 // if(size), result in bit
5109 // if(!size && ifx), conditional oper: if(left ^ right)
5110 symbol *tlbl = newiTempLabel (NULL);
5111 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5113 emitcode ("setb", "c");
5116 if ((AOP_TYPE (right) == AOP_LIT) &&
5117 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5119 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5123 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5124 emitcode ("xrl", "a,%s",
5125 aopGet (AOP (left), offset, FALSE, FALSE));
5127 emitcode ("jnz", "%05d$", tlbl->key + 100);
5133 emitcode ("", "%05d$:", tlbl->key + 100);
5137 jmpTrueOrFalse (ifx, tlbl);
5140 for (; (size--); offset++)
5143 // result = left & right
5144 if (AOP_TYPE (right) == AOP_LIT)
5146 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5148 aopPut (AOP (result),
5149 aopGet (AOP (left), offset, FALSE, FALSE),
5154 // faster than result <- left, anl result,right
5155 // and better if result is SFR
5156 if (AOP_TYPE (left) == AOP_ACC)
5157 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5160 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5161 emitcode ("xrl", "a,%s",
5162 aopGet (AOP (left), offset, FALSE, TRUE));
5164 aopPut (AOP (result), "a", offset);
5169 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5171 freeAsmop (result, NULL, ic, TRUE);
5174 /*-----------------------------------------------------------------*/
5175 /* genInline - write the inline code out */
5176 /*-----------------------------------------------------------------*/
5178 genInline (iCode * ic)
5180 char *buffer, *bp, *bp1;
5182 _G.inLine += (!options.asmpeep);
5184 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5185 strcpy (buffer, IC_INLINE (ic));
5187 /* emit each line as a code */
5212 /* emitcode("",buffer); */
5213 _G.inLine -= (!options.asmpeep);
5216 /*-----------------------------------------------------------------*/
5217 /* genRRC - rotate right with carry */
5218 /*-----------------------------------------------------------------*/
5222 operand *left, *result;
5223 int size, offset = 0;
5226 /* rotate right with carry */
5227 left = IC_LEFT (ic);
5228 result = IC_RESULT (ic);
5229 aopOp (left, ic, FALSE);
5230 aopOp (result, ic, FALSE);
5232 /* move it to the result */
5233 size = AOP_SIZE (result);
5238 l = aopGet (AOP (left), offset, FALSE, FALSE);
5240 emitcode ("rrc", "a");
5241 if (AOP_SIZE (result) > 1)
5242 aopPut (AOP (result), "a", offset--);
5244 /* now we need to put the carry into the
5245 highest order byte of the result */
5246 if (AOP_SIZE (result) > 1)
5248 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5251 emitcode ("mov", "acc.7,c");
5252 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5253 freeAsmop (left, NULL, ic, TRUE);
5254 freeAsmop (result, NULL, ic, TRUE);
5257 /*-----------------------------------------------------------------*/
5258 /* genRLC - generate code for rotate left with carry */
5259 /*-----------------------------------------------------------------*/
5263 operand *left, *result;
5264 int size, offset = 0;
5267 /* rotate right with carry */
5268 left = IC_LEFT (ic);
5269 result = IC_RESULT (ic);
5270 aopOp (left, ic, FALSE);
5271 aopOp (result, ic, FALSE);
5273 /* move it to the result */
5274 size = AOP_SIZE (result);
5278 l = aopGet (AOP (left), offset, FALSE, FALSE);
5280 emitcode ("add", "a,acc");
5281 if (AOP_SIZE (result) > 1)
5282 aopPut (AOP (result), "a", offset++);
5285 l = aopGet (AOP (left), offset, FALSE, FALSE);
5287 emitcode ("rlc", "a");
5288 if (AOP_SIZE (result) > 1)
5289 aopPut (AOP (result), "a", offset++);
5292 /* now we need to put the carry into the
5293 highest order byte of the result */
5294 if (AOP_SIZE (result) > 1)
5296 l = aopGet (AOP (result), 0, FALSE, FALSE);
5299 emitcode ("mov", "acc.0,c");
5300 aopPut (AOP (result), "a", 0);
5301 freeAsmop (left, NULL, ic, TRUE);
5302 freeAsmop (result, NULL, ic, TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* genGetHbit - generates code get highest order bit */
5307 /*-----------------------------------------------------------------*/
5309 genGetHbit (iCode * ic)
5311 operand *left, *result;
5312 left = IC_LEFT (ic);
5313 result = IC_RESULT (ic);
5314 aopOp (left, ic, FALSE);
5315 aopOp (result, ic, FALSE);
5317 /* get the highest order byte into a */
5318 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5319 if (AOP_TYPE (result) == AOP_CRY)
5321 emitcode ("rlc", "a");
5326 emitcode ("rl", "a");
5327 emitcode ("anl", "a,#0x01");
5332 freeAsmop (left, NULL, ic, TRUE);
5333 freeAsmop (result, NULL, ic, TRUE);
5336 /*-----------------------------------------------------------------*/
5337 /* AccRol - rotate left accumulator by known count */
5338 /*-----------------------------------------------------------------*/
5340 AccRol (int shCount)
5342 shCount &= 0x0007; // shCount : 0..7
5349 emitcode ("rl", "a");
5352 emitcode ("rl", "a");
5353 emitcode ("rl", "a");
5356 emitcode ("swap", "a");
5357 emitcode ("rr", "a");
5360 emitcode ("swap", "a");
5363 emitcode ("swap", "a");
5364 emitcode ("rl", "a");
5367 emitcode ("rr", "a");
5368 emitcode ("rr", "a");
5371 emitcode ("rr", "a");
5376 /*-----------------------------------------------------------------*/
5377 /* AccLsh - left shift accumulator by known count */
5378 /*-----------------------------------------------------------------*/
5380 AccLsh (int shCount)
5385 emitcode ("add", "a,acc");
5386 else if (shCount == 2)
5388 emitcode ("add", "a,acc");
5389 emitcode ("add", "a,acc");
5393 /* rotate left accumulator */
5395 /* and kill the lower order bits */
5396 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5401 /*-----------------------------------------------------------------*/
5402 /* AccRsh - right shift accumulator by known count */
5403 /*-----------------------------------------------------------------*/
5405 AccRsh (int shCount)
5412 emitcode ("rrc", "a");
5416 /* rotate right accumulator */
5417 AccRol (8 - shCount);
5418 /* and kill the higher order bits */
5419 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5424 /*-----------------------------------------------------------------*/
5425 /* AccSRsh - signed right shift accumulator by known count */
5426 /*-----------------------------------------------------------------*/
5428 AccSRsh (int shCount)
5435 emitcode ("mov", "c,acc.7");
5436 emitcode ("rrc", "a");
5438 else if (shCount == 2)
5440 emitcode ("mov", "c,acc.7");
5441 emitcode ("rrc", "a");
5442 emitcode ("mov", "c,acc.7");
5443 emitcode ("rrc", "a");
5447 tlbl = newiTempLabel (NULL);
5448 /* rotate right accumulator */
5449 AccRol (8 - shCount);
5450 /* and kill the higher order bits */
5451 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5452 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5453 emitcode ("orl", "a,#0x%02x",
5454 (unsigned char) ~SRMask[shCount]);
5455 emitcode ("", "%05d$:", tlbl->key + 100);
5460 /*-----------------------------------------------------------------*/
5461 /* shiftR1Left2Result - shift right one byte from left to result */
5462 /*-----------------------------------------------------------------*/
5464 shiftR1Left2Result (operand * left, int offl,
5465 operand * result, int offr,
5466 int shCount, int sign)
5468 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5469 /* shift right accumulator */
5474 aopPut (AOP (result), "a", offr);
5477 /*-----------------------------------------------------------------*/
5478 /* shiftL1Left2Result - shift left one byte from left to result */
5479 /*-----------------------------------------------------------------*/
5481 shiftL1Left2Result (operand * left, int offl,
5482 operand * result, int offr, int shCount)
5485 l = aopGet (AOP (left), offl, FALSE, FALSE);
5487 /* shift left accumulator */
5489 aopPut (AOP (result), "a", offr);
5492 /*-----------------------------------------------------------------*/
5493 /* movLeft2Result - move byte from left to result */
5494 /*-----------------------------------------------------------------*/
5496 movLeft2Result (operand * left, int offl,
5497 operand * result, int offr, int sign)
5500 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5502 l = aopGet (AOP (left), offl, FALSE, FALSE);
5504 if (*l == '@' && (IS_AOP_PREG (result)))
5506 emitcode ("mov", "a,%s", l);
5507 aopPut (AOP (result), "a", offr);
5512 aopPut (AOP (result), l, offr);
5515 /* MSB sign in acc.7 ! */
5516 if (getDataSize (left) == offl + 1)
5518 emitcode ("mov", "a,%s", l);
5519 aopPut (AOP (result), "a", offr);
5526 /*-----------------------------------------------------------------*/
5527 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5528 /*-----------------------------------------------------------------*/
5532 emitcode ("rrc", "a");
5533 emitcode ("xch", "a,%s", x);
5534 emitcode ("rrc", "a");
5535 emitcode ("xch", "a,%s", x);
5538 /*-----------------------------------------------------------------*/
5539 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5540 /*-----------------------------------------------------------------*/
5544 emitcode ("xch", "a,%s", x);
5545 emitcode ("rlc", "a");
5546 emitcode ("xch", "a,%s", x);
5547 emitcode ("rlc", "a");
5550 /*-----------------------------------------------------------------*/
5551 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5552 /*-----------------------------------------------------------------*/
5556 emitcode ("xch", "a,%s", x);
5557 emitcode ("add", "a,acc");
5558 emitcode ("xch", "a,%s", x);
5559 emitcode ("rlc", "a");
5562 /*-----------------------------------------------------------------*/
5563 /* AccAXLsh - left shift a:x by known count (0..7) */
5564 /*-----------------------------------------------------------------*/
5566 AccAXLsh (char *x, int shCount)
5581 case 5: // AAAAABBB:CCCCCDDD
5583 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5585 emitcode ("anl", "a,#0x%02x",
5586 SLMask[shCount]); // BBB00000:CCCCCDDD
5588 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5590 AccRol (shCount); // DDDCCCCC:BBB00000
5592 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5594 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5596 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5598 emitcode ("anl", "a,#0x%02x",
5599 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5601 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5603 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5606 case 6: // AAAAAABB:CCCCCCDD
5607 emitcode ("anl", "a,#0x%02x",
5608 SRMask[shCount]); // 000000BB:CCCCCCDD
5609 emitcode ("mov", "c,acc.0"); // c = B
5610 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5612 AccAXRrl1 (x); // BCCCCCCD:D000000B
5613 AccAXRrl1 (x); // BBCCCCCC:DD000000
5615 emitcode("rrc","a");
5616 emitcode("xch","a,%s", x);
5617 emitcode("rrc","a");
5618 emitcode("mov","c,acc.0"); //<< get correct bit
5619 emitcode("xch","a,%s", x);
5621 emitcode("rrc","a");
5622 emitcode("xch","a,%s", x);
5623 emitcode("rrc","a");
5624 emitcode("xch","a,%s", x);
5627 case 7: // a:x <<= 7
5629 emitcode ("anl", "a,#0x%02x",
5630 SRMask[shCount]); // 0000000B:CCCCCCCD
5632 emitcode ("mov", "c,acc.0"); // c = B
5634 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5636 AccAXRrl1 (x); // BCCCCCCC:D0000000
5644 /*-----------------------------------------------------------------*/
5645 /* AccAXRsh - right shift a:x known count (0..7) */
5646 /*-----------------------------------------------------------------*/
5648 AccAXRsh (char *x, int shCount)
5656 AccAXRrl1 (x); // 0->a:x
5661 AccAXRrl1 (x); // 0->a:x
5664 AccAXRrl1 (x); // 0->a:x
5669 case 5: // AAAAABBB:CCCCCDDD = a:x
5671 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5673 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5675 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5677 emitcode ("anl", "a,#0x%02x",
5678 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5680 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5682 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5684 emitcode ("anl", "a,#0x%02x",
5685 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5687 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5689 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5691 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5694 case 6: // AABBBBBB:CCDDDDDD
5696 emitcode ("mov", "c,acc.7");
5697 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5699 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5701 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5703 emitcode ("anl", "a,#0x%02x",
5704 SRMask[shCount]); // 000000AA:BBBBBBCC
5707 case 7: // ABBBBBBB:CDDDDDDD
5709 emitcode ("mov", "c,acc.7"); // c = A
5711 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5713 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5715 emitcode ("anl", "a,#0x%02x",
5716 SRMask[shCount]); // 0000000A:BBBBBBBC
5724 /*-----------------------------------------------------------------*/
5725 /* AccAXRshS - right shift signed a:x known count (0..7) */
5726 /*-----------------------------------------------------------------*/
5728 AccAXRshS (char *x, int shCount)
5736 emitcode ("mov", "c,acc.7");
5737 AccAXRrl1 (x); // s->a:x
5741 emitcode ("mov", "c,acc.7");
5742 AccAXRrl1 (x); // s->a:x
5744 emitcode ("mov", "c,acc.7");
5745 AccAXRrl1 (x); // s->a:x
5750 case 5: // AAAAABBB:CCCCCDDD = a:x
5752 tlbl = newiTempLabel (NULL);
5753 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5755 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5757 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5759 emitcode ("anl", "a,#0x%02x",
5760 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5762 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5764 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5766 emitcode ("anl", "a,#0x%02x",
5767 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5769 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5771 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5773 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5775 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5776 emitcode ("orl", "a,#0x%02x",
5777 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5779 emitcode ("", "%05d$:", tlbl->key + 100);
5780 break; // SSSSAAAA:BBBCCCCC
5782 case 6: // AABBBBBB:CCDDDDDD
5784 tlbl = newiTempLabel (NULL);
5785 emitcode ("mov", "c,acc.7");
5786 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5788 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5790 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5792 emitcode ("anl", "a,#0x%02x",
5793 SRMask[shCount]); // 000000AA:BBBBBBCC
5795 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5796 emitcode ("orl", "a,#0x%02x",
5797 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5799 emitcode ("", "%05d$:", tlbl->key + 100);
5801 case 7: // ABBBBBBB:CDDDDDDD
5803 tlbl = newiTempLabel (NULL);
5804 emitcode ("mov", "c,acc.7"); // c = A
5806 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5808 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5810 emitcode ("anl", "a,#0x%02x",
5811 SRMask[shCount]); // 0000000A:BBBBBBBC
5813 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5814 emitcode ("orl", "a,#0x%02x",
5815 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5817 emitcode ("", "%05d$:", tlbl->key + 100);
5824 /*-----------------------------------------------------------------*/
5825 /* shiftL2Left2Result - shift left two bytes from left to result */
5826 /*-----------------------------------------------------------------*/
5828 shiftL2Left2Result (operand * left, int offl,
5829 operand * result, int offr, int shCount)
5831 if (sameRegs (AOP (result), AOP (left)) &&
5832 ((offl + MSB16) == offr))
5834 /* don't crash result[offr] */
5835 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5836 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5840 movLeft2Result (left, offl, result, offr, 0);
5841 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5843 /* ax << shCount (x = lsb(result)) */
5844 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5845 aopPut (AOP (result), "a", offr + MSB16);
5849 /*-----------------------------------------------------------------*/
5850 /* shiftR2Left2Result - shift right two bytes from left to result */
5851 /*-----------------------------------------------------------------*/
5853 shiftR2Left2Result (operand * left, int offl,
5854 operand * result, int offr,
5855 int shCount, int sign)
5857 if (sameRegs (AOP (result), AOP (left)) &&
5858 ((offl + MSB16) == offr))
5860 /* don't crash result[offr] */
5861 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5862 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5866 movLeft2Result (left, offl, result, offr, 0);
5867 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5869 /* a:x >> shCount (x = lsb(result)) */
5871 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5873 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5874 if (getDataSize (result) > 1)
5875 aopPut (AOP (result), "a", offr + MSB16);
5878 /*-----------------------------------------------------------------*/
5879 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5880 /*-----------------------------------------------------------------*/
5882 shiftLLeftOrResult (operand * left, int offl,
5883 operand * result, int offr, int shCount)
5885 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5886 /* shift left accumulator */
5888 /* or with result */
5889 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5890 /* back to result */
5891 aopPut (AOP (result), "a", offr);
5894 /*-----------------------------------------------------------------*/
5895 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5896 /*-----------------------------------------------------------------*/
5898 shiftRLeftOrResult (operand * left, int offl,
5899 operand * result, int offr, int shCount)
5901 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5902 /* shift right accumulator */
5904 /* or with result */
5905 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5906 /* back to result */
5907 aopPut (AOP (result), "a", offr);
5910 /*-----------------------------------------------------------------*/
5911 /* genlshOne - left shift a one byte quantity by known count */
5912 /*-----------------------------------------------------------------*/
5914 genlshOne (operand * result, operand * left, int shCount)
5916 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5919 /*-----------------------------------------------------------------*/
5920 /* genlshTwo - left shift two bytes by known amount != 0 */
5921 /*-----------------------------------------------------------------*/
5923 genlshTwo (operand * result, operand * left, int shCount)
5927 size = getDataSize (result);
5929 /* if shCount >= 8 */
5937 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5939 movLeft2Result (left, LSB, result, MSB16, 0);
5941 aopPut (AOP (result), zero, LSB);
5944 /* 1 <= shCount <= 7 */
5948 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5950 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5954 /*-----------------------------------------------------------------*/
5955 /* shiftLLong - shift left one long from left to result */
5956 /* offl = LSB or MSB16 */
5957 /*-----------------------------------------------------------------*/
5959 shiftLLong (operand * left, operand * result, int offr)
5962 int size = AOP_SIZE (result);
5964 if (size >= LSB + offr)
5966 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5968 emitcode ("add", "a,acc");
5969 if (sameRegs (AOP (left), AOP (result)) &&
5970 size >= MSB16 + offr && offr != LSB)
5971 emitcode ("xch", "a,%s",
5972 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5974 aopPut (AOP (result), "a", LSB + offr);
5977 if (size >= MSB16 + offr)
5979 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5981 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5984 emitcode ("rlc", "a");
5985 if (sameRegs (AOP (left), AOP (result)) &&
5986 size >= MSB24 + offr && offr != LSB)
5987 emitcode ("xch", "a,%s",
5988 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5990 aopPut (AOP (result), "a", MSB16 + offr);
5993 if (size >= MSB24 + offr)
5995 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5997 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6000 emitcode ("rlc", "a");
6001 if (sameRegs (AOP (left), AOP (result)) &&
6002 size >= MSB32 + offr && offr != LSB)
6003 emitcode ("xch", "a,%s",
6004 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6006 aopPut (AOP (result), "a", MSB24 + offr);
6009 if (size > MSB32 + offr)
6011 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6013 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6016 emitcode ("rlc", "a");
6017 aopPut (AOP (result), "a", MSB32 + offr);
6020 aopPut (AOP (result), zero, LSB);
6023 /*-----------------------------------------------------------------*/
6024 /* genlshFour - shift four byte by a known amount != 0 */
6025 /*-----------------------------------------------------------------*/
6027 genlshFour (operand * result, operand * left, int shCount)
6031 size = AOP_SIZE (result);
6033 /* if shifting more that 3 bytes */
6038 /* lowest order of left goes to the highest
6039 order of the destination */
6040 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6042 movLeft2Result (left, LSB, result, MSB32, 0);
6043 aopPut (AOP (result), zero, LSB);
6044 aopPut (AOP (result), zero, MSB16);
6045 aopPut (AOP (result), zero, MSB24);
6049 /* more than two bytes */
6050 else if (shCount >= 16)
6052 /* lower order two bytes goes to higher order two bytes */
6054 /* if some more remaining */
6056 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6059 movLeft2Result (left, MSB16, result, MSB32, 0);
6060 movLeft2Result (left, LSB, result, MSB24, 0);
6062 aopPut (AOP (result), zero, MSB16);
6063 aopPut (AOP (result), zero, LSB);
6067 /* if more than 1 byte */
6068 else if (shCount >= 8)
6070 /* lower order three bytes goes to higher order three bytes */
6075 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6077 movLeft2Result (left, LSB, result, MSB16, 0);
6083 movLeft2Result (left, MSB24, result, MSB32, 0);
6084 movLeft2Result (left, MSB16, result, MSB24, 0);
6085 movLeft2Result (left, LSB, result, MSB16, 0);
6086 aopPut (AOP (result), zero, LSB);
6088 else if (shCount == 1)
6089 shiftLLong (left, result, MSB16);
6092 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6093 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6094 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6095 aopPut (AOP (result), zero, LSB);
6100 /* 1 <= shCount <= 7 */
6101 else if (shCount <= 2)
6103 shiftLLong (left, result, LSB);
6105 shiftLLong (result, result, LSB);
6107 /* 3 <= shCount <= 7, optimize */
6110 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6111 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6112 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6116 /*-----------------------------------------------------------------*/
6117 /* genLeftShiftLiteral - left shifting by known count */
6118 /*-----------------------------------------------------------------*/
6120 genLeftShiftLiteral (operand * left,
6125 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6128 freeAsmop (right, NULL, ic, TRUE);
6130 aopOp (left, ic, FALSE);
6131 aopOp (result, ic, FALSE);
6133 size = getSize (operandType (result));
6136 emitcode ("; shift left ", "result %d, left %d", size,
6140 /* I suppose that the left size >= result size */
6145 movLeft2Result (left, size, result, size, 0);
6149 else if (shCount >= (size * 8))
6151 aopPut (AOP (result), zero, size);
6157 genlshOne (result, left, shCount);
6162 genlshTwo (result, left, shCount);
6166 genlshFour (result, left, shCount);
6170 freeAsmop (left, NULL, ic, TRUE);
6171 freeAsmop (result, NULL, ic, TRUE);
6174 /*-----------------------------------------------------------------*/
6175 /* genLeftShift - generates code for left shifting */
6176 /*-----------------------------------------------------------------*/
6178 genLeftShift (iCode * ic)
6180 operand *left, *right, *result;
6183 symbol *tlbl, *tlbl1;
6185 right = IC_RIGHT (ic);
6186 left = IC_LEFT (ic);
6187 result = IC_RESULT (ic);
6189 aopOp (right, ic, FALSE);
6191 /* if the shift count is known then do it
6192 as efficiently as possible */
6193 if (AOP_TYPE (right) == AOP_LIT)
6195 genLeftShiftLiteral (left, right, result, ic);
6199 /* shift count is unknown then we have to form
6200 a loop get the loop count in B : Note: we take
6201 only the lower order byte since shifting
6202 more that 32 bits make no sense anyway, ( the
6203 largest size of an object can be only 32 bits ) */
6205 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6206 emitcode ("inc", "b");
6207 freeAsmop (right, NULL, ic, TRUE);
6208 aopOp (left, ic, FALSE);
6209 aopOp (result, ic, FALSE);
6211 /* now move the left to the result if they are not the
6213 if (!sameRegs (AOP (left), AOP (result)) &&
6214 AOP_SIZE (result) > 1)
6217 size = AOP_SIZE (result);
6221 l = aopGet (AOP (left), offset, FALSE, TRUE);
6222 if (*l == '@' && (IS_AOP_PREG (result)))
6225 emitcode ("mov", "a,%s", l);
6226 aopPut (AOP (result), "a", offset);
6229 aopPut (AOP (result), l, offset);
6234 tlbl = newiTempLabel (NULL);
6235 size = AOP_SIZE (result);
6237 tlbl1 = newiTempLabel (NULL);
6239 /* if it is only one byte then */
6242 symbol *tlbl1 = newiTempLabel (NULL);
6244 l = aopGet (AOP (left), 0, FALSE, FALSE);
6246 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6247 emitcode ("", "%05d$:", tlbl->key + 100);
6248 emitcode ("add", "a,acc");
6249 emitcode ("", "%05d$:", tlbl1->key + 100);
6250 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6251 aopPut (AOP (result), "a", 0);
6255 reAdjustPreg (AOP (result));
6257 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6258 emitcode ("", "%05d$:", tlbl->key + 100);
6259 l = aopGet (AOP (result), offset, FALSE, FALSE);
6261 emitcode ("add", "a,acc");
6262 aopPut (AOP (result), "a", offset++);
6265 l = aopGet (AOP (result), offset, FALSE, FALSE);
6267 emitcode ("rlc", "a");
6268 aopPut (AOP (result), "a", offset++);
6270 reAdjustPreg (AOP (result));
6272 emitcode ("", "%05d$:", tlbl1->key + 100);
6273 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6275 freeAsmop (left, NULL, ic, TRUE);
6276 freeAsmop (result, NULL, ic, TRUE);
6279 /*-----------------------------------------------------------------*/
6280 /* genrshOne - right shift a one byte quantity by known count */
6281 /*-----------------------------------------------------------------*/
6283 genrshOne (operand * result, operand * left,
6284 int shCount, int sign)
6286 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6289 /*-----------------------------------------------------------------*/
6290 /* genrshTwo - right shift two bytes by known amount != 0 */
6291 /*-----------------------------------------------------------------*/
6293 genrshTwo (operand * result, operand * left,
6294 int shCount, int sign)
6296 /* if shCount >= 8 */
6301 shiftR1Left2Result (left, MSB16, result, LSB,
6304 movLeft2Result (left, MSB16, result, LSB, sign);
6305 addSign (result, MSB16, sign);
6308 /* 1 <= shCount <= 7 */
6310 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6313 /*-----------------------------------------------------------------*/
6314 /* shiftRLong - shift right one long from left to result */
6315 /* offl = LSB or MSB16 */
6316 /*-----------------------------------------------------------------*/
6318 shiftRLong (operand * left, int offl,
6319 operand * result, int sign)
6322 emitcode ("clr", "c");
6323 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6325 emitcode ("mov", "c,acc.7");
6326 emitcode ("rrc", "a");
6327 aopPut (AOP (result), "a", MSB32 - offl);
6329 /* add sign of "a" */
6330 addSign (result, MSB32, sign);
6332 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6333 emitcode ("rrc", "a");
6334 aopPut (AOP (result), "a", MSB24 - offl);
6336 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6337 emitcode ("rrc", "a");
6338 aopPut (AOP (result), "a", MSB16 - offl);
6342 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6343 emitcode ("rrc", "a");
6344 aopPut (AOP (result), "a", LSB);
6348 /*-----------------------------------------------------------------*/
6349 /* genrshFour - shift four byte by a known amount != 0 */
6350 /*-----------------------------------------------------------------*/
6352 genrshFour (operand * result, operand * left,
6353 int shCount, int sign)
6355 /* if shifting more that 3 bytes */
6360 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6362 movLeft2Result (left, MSB32, result, LSB, sign);
6363 addSign (result, MSB16, sign);
6365 else if (shCount >= 16)
6369 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6372 movLeft2Result (left, MSB24, result, LSB, 0);
6373 movLeft2Result (left, MSB32, result, MSB16, sign);
6375 addSign (result, MSB24, sign);
6377 else if (shCount >= 8)
6381 shiftRLong (left, MSB16, result, sign);
6382 else if (shCount == 0)
6384 movLeft2Result (left, MSB16, result, LSB, 0);
6385 movLeft2Result (left, MSB24, result, MSB16, 0);
6386 movLeft2Result (left, MSB32, result, MSB24, sign);
6387 addSign (result, MSB32, sign);
6391 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6392 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6393 /* the last shift is signed */
6394 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6395 addSign (result, MSB32, sign);
6399 { /* 1 <= shCount <= 7 */
6402 shiftRLong (left, LSB, result, sign);
6404 shiftRLong (result, LSB, result, sign);
6408 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6409 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6410 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6415 /*-----------------------------------------------------------------*/
6416 /* genRightShiftLiteral - right shifting by known count */
6417 /*-----------------------------------------------------------------*/
6419 genRightShiftLiteral (operand * left,
6425 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6428 freeAsmop (right, NULL, ic, TRUE);
6430 aopOp (left, ic, FALSE);
6431 aopOp (result, ic, FALSE);
6434 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6438 size = getDataSize (left);
6439 /* test the LEFT size !!! */
6441 /* I suppose that the left size >= result size */
6444 size = getDataSize (result);
6446 movLeft2Result (left, size, result, size, 0);
6449 else if (shCount >= (size * 8))
6452 /* get sign in acc.7 */
6453 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6454 addSign (result, LSB, sign);
6461 genrshOne (result, left, shCount, sign);
6465 genrshTwo (result, left, shCount, sign);
6469 genrshFour (result, left, shCount, sign);
6475 freeAsmop (left, NULL, ic, TRUE);
6476 freeAsmop (result, NULL, ic, TRUE);
6480 /*-----------------------------------------------------------------*/
6481 /* genSignedRightShift - right shift of signed number */
6482 /*-----------------------------------------------------------------*/
6484 genSignedRightShift (iCode * ic)
6486 operand *right, *left, *result;
6489 symbol *tlbl, *tlbl1;
6491 /* we do it the hard way put the shift count in b
6492 and loop thru preserving the sign */
6494 right = IC_RIGHT (ic);
6495 left = IC_LEFT (ic);
6496 result = IC_RESULT (ic);
6498 aopOp (right, ic, FALSE);
6501 if (AOP_TYPE (right) == AOP_LIT)
6503 genRightShiftLiteral (left, right, result, ic, 1);
6506 /* shift count is unknown then we have to form
6507 a loop get the loop count in B : Note: we take
6508 only the lower order byte since shifting
6509 more that 32 bits make no sense anyway, ( the
6510 largest size of an object can be only 32 bits ) */
6512 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6513 emitcode ("inc", "b");
6514 freeAsmop (right, NULL, ic, TRUE);
6515 aopOp (left, ic, FALSE);
6516 aopOp (result, ic, FALSE);
6518 /* now move the left to the result if they are not the
6520 if (!sameRegs (AOP (left), AOP (result)) &&
6521 AOP_SIZE (result) > 1)
6524 size = AOP_SIZE (result);
6528 l = aopGet (AOP (left), offset, FALSE, TRUE);
6529 if (*l == '@' && IS_AOP_PREG (result))
6532 emitcode ("mov", "a,%s", l);
6533 aopPut (AOP (result), "a", offset);
6536 aopPut (AOP (result), l, offset);
6541 /* mov the highest order bit to OVR */
6542 tlbl = newiTempLabel (NULL);
6543 tlbl1 = newiTempLabel (NULL);
6545 size = AOP_SIZE (result);
6547 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6548 emitcode ("rlc", "a");
6549 emitcode ("mov", "ov,c");
6550 /* if it is only one byte then */
6553 l = aopGet (AOP (left), 0, FALSE, FALSE);
6555 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6556 emitcode ("", "%05d$:", tlbl->key + 100);
6557 emitcode ("mov", "c,ov");
6558 emitcode ("rrc", "a");
6559 emitcode ("", "%05d$:", tlbl1->key + 100);
6560 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6561 aopPut (AOP (result), "a", 0);
6565 reAdjustPreg (AOP (result));
6566 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6567 emitcode ("", "%05d$:", tlbl->key + 100);
6568 emitcode ("mov", "c,ov");
6571 l = aopGet (AOP (result), offset, FALSE, FALSE);
6573 emitcode ("rrc", "a");
6574 aopPut (AOP (result), "a", offset--);
6576 reAdjustPreg (AOP (result));
6577 emitcode ("", "%05d$:", tlbl1->key + 100);
6578 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6581 freeAsmop (left, NULL, ic, TRUE);
6582 freeAsmop (result, NULL, ic, TRUE);
6585 /*-----------------------------------------------------------------*/
6586 /* genRightShift - generate code for right shifting */
6587 /*-----------------------------------------------------------------*/
6589 genRightShift (iCode * ic)
6591 operand *right, *left, *result;
6595 symbol *tlbl, *tlbl1;
6597 /* if signed then we do it the hard way preserve the
6598 sign bit moving it inwards */
6599 retype = getSpec (operandType (IC_RESULT (ic)));
6601 if (!SPEC_USIGN (retype))
6603 genSignedRightShift (ic);
6607 /* signed & unsigned types are treated the same : i.e. the
6608 signed is NOT propagated inwards : quoting from the
6609 ANSI - standard : "for E1 >> E2, is equivalent to division
6610 by 2**E2 if unsigned or if it has a non-negative value,
6611 otherwise the result is implementation defined ", MY definition
6612 is that the sign does not get propagated */
6614 right = IC_RIGHT (ic);
6615 left = IC_LEFT (ic);
6616 result = IC_RESULT (ic);
6618 aopOp (right, ic, FALSE);
6620 /* if the shift count is known then do it
6621 as efficiently as possible */
6622 if (AOP_TYPE (right) == AOP_LIT)
6624 genRightShiftLiteral (left, right, result, ic, 0);
6628 /* shift count is unknown then we have to form
6629 a loop get the loop count in B : Note: we take
6630 only the lower order byte since shifting
6631 more that 32 bits make no sense anyway, ( the
6632 largest size of an object can be only 32 bits ) */
6634 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6635 emitcode ("inc", "b");
6636 freeAsmop (right, NULL, ic, TRUE);
6637 aopOp (left, ic, FALSE);
6638 aopOp (result, ic, FALSE);
6640 /* now move the left to the result if they are not the
6642 if (!sameRegs (AOP (left), AOP (result)) &&
6643 AOP_SIZE (result) > 1)
6646 size = AOP_SIZE (result);
6650 l = aopGet (AOP (left), offset, FALSE, TRUE);
6651 if (*l == '@' && IS_AOP_PREG (result))
6654 emitcode ("mov", "a,%s", l);
6655 aopPut (AOP (result), "a", offset);
6658 aopPut (AOP (result), l, offset);
6663 tlbl = newiTempLabel (NULL);
6664 tlbl1 = newiTempLabel (NULL);
6665 size = AOP_SIZE (result);
6668 /* if it is only one byte then */
6671 l = aopGet (AOP (left), 0, FALSE, FALSE);
6673 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6674 emitcode ("", "%05d$:", tlbl->key + 100);
6676 emitcode ("rrc", "a");
6677 emitcode ("", "%05d$:", tlbl1->key + 100);
6678 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6679 aopPut (AOP (result), "a", 0);
6683 reAdjustPreg (AOP (result));
6684 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6685 emitcode ("", "%05d$:", tlbl->key + 100);
6689 l = aopGet (AOP (result), offset, FALSE, FALSE);
6691 emitcode ("rrc", "a");
6692 aopPut (AOP (result), "a", offset--);
6694 reAdjustPreg (AOP (result));
6696 emitcode ("", "%05d$:", tlbl1->key + 100);
6697 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6700 freeAsmop (left, NULL, ic, TRUE);
6701 freeAsmop (result, NULL, ic, TRUE);
6704 /*-----------------------------------------------------------------*/
6705 /* genUnpackBits - generates code for unpacking bits */
6706 /*-----------------------------------------------------------------*/
6708 genUnpackBits (operand * result, char *rname, int ptype)
6716 etype = getSpec (operandType (result));
6717 rsize = getSize (operandType (result));
6718 /* read the first byte */
6724 emitcode ("mov", "a,@%s", rname);
6728 emitcode ("movx", "a,@%s", rname);
6732 emitcode ("movx", "a,@dptr");
6736 emitcode ("clr", "a");
6737 emitcode ("movc", "a,%s", "@a+dptr");
6741 emitcode ("lcall", "__gptrget");
6745 rlen = SPEC_BLEN (etype);
6747 /* if we have bitdisplacement then it fits */
6748 /* into this byte completely or if length is */
6749 /* less than a byte */
6750 if ((shCnt = SPEC_BSTR (etype)) ||
6751 (SPEC_BLEN (etype) <= 8))
6754 /* shift right acc */
6757 emitcode ("anl", "a,#0x%02x",
6758 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6759 aopPut (AOP (result), "a", offset++);
6763 /* bit field did not fit in a byte */
6764 aopPut (AOP (result), "a", offset++);
6773 emitcode ("inc", "%s", rname);
6774 emitcode ("mov", "a,@%s", rname);
6778 emitcode ("inc", "%s", rname);
6779 emitcode ("movx", "a,@%s", rname);
6783 emitcode ("inc", "dptr");
6784 emitcode ("movx", "a,@dptr");
6788 emitcode ("clr", "a");
6789 emitcode ("inc", "dptr");
6790 emitcode ("movc", "a", "@a+dptr");
6794 emitcode ("inc", "dptr");
6795 emitcode ("lcall", "__gptrget");
6800 /* if we are done */
6804 aopPut (AOP (result), "a", offset++);
6810 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6812 aopPut (AOP (result), "a", offset++);
6820 aopPut (AOP (result), zero, offset++);
6826 /*-----------------------------------------------------------------*/
6827 /* genDataPointerGet - generates code when ptr offset is known */
6828 /*-----------------------------------------------------------------*/
6830 genDataPointerGet (operand * left,
6836 int size, offset = 0;
6837 aopOp (result, ic, TRUE);
6839 /* get the string representation of the name */
6840 l = aopGet (AOP (left), 0, FALSE, TRUE);
6841 size = AOP_SIZE (result);
6845 sprintf (buffer, "(%s + %d)", l + 1, offset);
6847 sprintf (buffer, "%s", l + 1);
6848 aopPut (AOP (result), buffer, offset++);
6851 freeAsmop (left, NULL, ic, TRUE);
6852 freeAsmop (result, NULL, ic, TRUE);
6855 /*-----------------------------------------------------------------*/
6856 /* genNearPointerGet - emitcode for near pointer fetch */
6857 /*-----------------------------------------------------------------*/
6859 genNearPointerGet (operand * left,
6867 sym_link *rtype, *retype;
6868 sym_link *ltype = operandType (left);
6871 rtype = operandType (result);
6872 retype = getSpec (rtype);
6874 aopOp (left, ic, FALSE);
6876 /* if left is rematerialisable and
6877 result is not bit variable type and
6878 the left is pointer to data space i.e
6879 lower 128 bytes of space */
6880 if (AOP_TYPE (left) == AOP_IMMD &&
6881 !IS_BITVAR (retype) &&
6882 DCL_TYPE (ltype) == POINTER)
6884 genDataPointerGet (left, result, ic);
6888 /* if the value is already in a pointer register
6889 then don't need anything more */
6890 if (!AOP_INPREG (AOP (left)))
6892 /* otherwise get a free pointer register */
6894 preg = getFreePtr (ic, &aop, FALSE);
6895 emitcode ("mov", "%s,%s",
6897 aopGet (AOP (left), 0, FALSE, TRUE));
6901 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6903 aopOp (result, ic, FALSE);
6905 /* if bitfield then unpack the bits */
6906 if (IS_BITVAR (retype))
6907 genUnpackBits (result, rname, POINTER);
6910 /* we have can just get the values */
6911 int size = AOP_SIZE (result);
6916 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6919 emitcode ("mov", "a,@%s", rname);
6920 aopPut (AOP (result), "a", offset);
6924 sprintf (buffer, "@%s", rname);
6925 aopPut (AOP (result), buffer, offset);
6929 emitcode ("inc", "%s", rname);
6933 /* now some housekeeping stuff */
6934 if (aop) /* we had to allocate for this iCode */
6936 if (pi) { /* post increment present */
6937 aopPut(AOP ( left ),rname,0);
6939 freeAsmop (NULL, aop, ic, TRUE);
6943 /* we did not allocate which means left
6944 already in a pointer register, then
6945 if size > 0 && this could be used again
6946 we have to point it back to where it
6948 if ((AOP_SIZE (result) > 1 &&
6949 !OP_SYMBOL (left)->remat &&
6950 (OP_SYMBOL (left)->liveTo > ic->seq ||
6954 int size = AOP_SIZE (result) - 1;
6956 emitcode ("dec", "%s", rname);
6961 freeAsmop (left, NULL, ic, TRUE);
6962 freeAsmop (result, NULL, ic, TRUE);
6963 if (pi) pi->generated = 1;
6966 /*-----------------------------------------------------------------*/
6967 /* genPagedPointerGet - emitcode for paged pointer fetch */
6968 /*-----------------------------------------------------------------*/
6970 genPagedPointerGet (operand * left,
6978 sym_link *rtype, *retype;
6980 rtype = operandType (result);
6981 retype = getSpec (rtype);
6983 aopOp (left, ic, FALSE);
6985 /* if the value is already in a pointer register
6986 then don't need anything more */
6987 if (!AOP_INPREG (AOP (left)))
6989 /* otherwise get a free pointer register */
6991 preg = getFreePtr (ic, &aop, FALSE);
6992 emitcode ("mov", "%s,%s",
6994 aopGet (AOP (left), 0, FALSE, TRUE));
6998 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7000 aopOp (result, ic, FALSE);
7002 /* if bitfield then unpack the bits */
7003 if (IS_BITVAR (retype))
7004 genUnpackBits (result, rname, PPOINTER);
7007 /* we have can just get the values */
7008 int size = AOP_SIZE (result);
7014 emitcode ("movx", "a,@%s", rname);
7015 aopPut (AOP (result), "a", offset);
7020 emitcode ("inc", "%s", rname);
7024 /* now some housekeeping stuff */
7025 if (aop) /* we had to allocate for this iCode */
7027 if (pi) aopPut ( AOP (left), rname, 0);
7028 freeAsmop (NULL, aop, ic, TRUE);
7032 /* we did not allocate which means left
7033 already in a pointer register, then
7034 if size > 0 && this could be used again
7035 we have to point it back to where it
7037 if ((AOP_SIZE (result) > 1 &&
7038 !OP_SYMBOL (left)->remat &&
7039 (OP_SYMBOL (left)->liveTo > ic->seq ||
7043 int size = AOP_SIZE (result) - 1;
7045 emitcode ("dec", "%s", rname);
7050 freeAsmop (left, NULL, ic, TRUE);
7051 freeAsmop (result, NULL, ic, TRUE);
7052 if (pi) pi->generated = 1;
7056 /*-----------------------------------------------------------------*/
7057 /* genFarPointerGet - gget value from far space */
7058 /*-----------------------------------------------------------------*/
7060 genFarPointerGet (operand * left,
7061 operand * result, iCode * ic, iCode * pi)
7064 sym_link *retype = getSpec (operandType (result));
7066 aopOp (left, ic, FALSE);
7068 /* if the operand is already in dptr
7069 then we do nothing else we move the value to dptr */
7070 if (AOP_TYPE (left) != AOP_STR)
7072 /* if this is remateriazable */
7073 if (AOP_TYPE (left) == AOP_IMMD)
7074 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7076 { /* we need to get it byte by byte */
7077 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7078 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7081 /* so dptr know contains the address */
7082 aopOp (result, ic, FALSE);
7084 /* if bit then unpack */
7085 if (IS_BITVAR (retype))
7086 genUnpackBits (result, "dptr", FPOINTER);
7089 size = AOP_SIZE (result);
7094 emitcode ("movx", "a,@dptr");
7095 aopPut (AOP (result), "a", offset++);
7097 emitcode ("inc", "dptr");
7101 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7102 aopPut ( AOP (left), "dpl", 0);
7103 aopPut ( AOP (left), "dph", 1);
7106 freeAsmop (left, NULL, ic, TRUE);
7107 freeAsmop (result, NULL, ic, TRUE);
7110 /*-----------------------------------------------------------------*/
7111 /* genCodePointerGet - gget value from code space */
7112 /*-----------------------------------------------------------------*/
7114 genCodePointerGet (operand * left,
7115 operand * result, iCode * ic, iCode *pi)
7118 sym_link *retype = getSpec (operandType (result));
7120 aopOp (left, ic, FALSE);
7122 /* if the operand is already in dptr
7123 then we do nothing else we move the value to dptr */
7124 if (AOP_TYPE (left) != AOP_STR)
7126 /* if this is remateriazable */
7127 if (AOP_TYPE (left) == AOP_IMMD)
7128 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7130 { /* we need to get it byte by byte */
7131 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7132 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7135 /* so dptr know contains the address */
7136 aopOp (result, ic, FALSE);
7138 /* if bit then unpack */
7139 if (IS_BITVAR (retype))
7140 genUnpackBits (result, "dptr", CPOINTER);
7143 size = AOP_SIZE (result);
7148 emitcode ("clr", "a");
7149 emitcode ("movc", "a,@a+dptr");
7150 aopPut (AOP (result), "a", offset++);
7152 emitcode ("inc", "dptr");
7156 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7157 aopPut ( AOP (left), "dpl", 0);
7158 aopPut ( AOP (left), "dph", 1);
7161 freeAsmop (left, NULL, ic, TRUE);
7162 freeAsmop (result, NULL, ic, TRUE);
7165 /*-----------------------------------------------------------------*/
7166 /* genGenPointerGet - gget value from generic pointer space */
7167 /*-----------------------------------------------------------------*/
7169 genGenPointerGet (operand * left,
7170 operand * result, iCode * ic, iCode *pi)
7173 sym_link *retype = getSpec (operandType (result));
7175 aopOp (left, ic, FALSE);
7177 /* if the operand is already in dptr
7178 then we do nothing else we move the value to dptr */
7179 if (AOP_TYPE (left) != AOP_STR)
7181 /* if this is remateriazable */
7182 if (AOP_TYPE (left) == AOP_IMMD)
7184 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7185 emitcode ("mov", "b,#%d", pointerCode (retype));
7188 { /* we need to get it byte by byte */
7189 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7190 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7191 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7194 /* so dptr know contains the address */
7195 aopOp (result, ic, FALSE);
7197 /* if bit then unpack */
7198 if (IS_BITVAR (retype))
7199 genUnpackBits (result, "dptr", GPOINTER);
7202 size = AOP_SIZE (result);
7207 emitcode ("lcall", "__gptrget");
7208 aopPut (AOP (result), "a", offset++);
7210 emitcode ("inc", "dptr");
7214 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7215 aopPut ( AOP (left), "dpl", 0);
7216 aopPut ( AOP (left), "dph", 1);
7219 freeAsmop (left, NULL, ic, TRUE);
7220 freeAsmop (result, NULL, ic, TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genPointerGet - generate code for pointer get */
7225 /*-----------------------------------------------------------------*/
7227 genPointerGet (iCode * ic, iCode *pi)
7229 operand *left, *result;
7230 sym_link *type, *etype;
7233 left = IC_LEFT (ic);
7234 result = IC_RESULT (ic);
7236 /* depending on the type of pointer we need to
7237 move it to the correct pointer register */
7238 type = operandType (left);
7239 etype = getSpec (type);
7240 /* if left is of type of pointer then it is simple */
7241 if (IS_PTR (type) && !IS_FUNC (type->next))
7242 p_type = DCL_TYPE (type);
7245 /* we have to go by the storage class */
7246 p_type = PTR_TYPE (SPEC_OCLS (etype));
7249 /* now that we have the pointer type we assign
7250 the pointer values */
7256 genNearPointerGet (left, result, ic, pi);
7260 genPagedPointerGet (left, result, ic, pi);
7264 genFarPointerGet (left, result, ic, pi);
7268 genCodePointerGet (left, result, ic, pi);
7272 genGenPointerGet (left, result, ic, pi);
7278 /*-----------------------------------------------------------------*/
7279 /* genPackBits - generates code for packed bit storage */
7280 /*-----------------------------------------------------------------*/
7282 genPackBits (sym_link * etype,
7284 char *rname, int p_type)
7292 blen = SPEC_BLEN (etype);
7293 bstr = SPEC_BSTR (etype);
7295 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7298 /* if the bit lenth is less than or */
7299 /* it exactly fits a byte then */
7300 if (SPEC_BLEN (etype) <= 8)
7302 shCount = SPEC_BSTR (etype);
7304 /* shift left acc */
7307 if (SPEC_BLEN (etype) < 8)
7308 { /* if smaller than a byte */
7314 emitcode ("mov", "b,a");
7315 emitcode ("mov", "a,@%s", rname);
7319 emitcode ("mov", "b,a");
7320 emitcode ("movx", "a,@dptr");
7324 emitcode ("push", "b");
7325 emitcode ("push", "acc");
7326 emitcode ("lcall", "__gptrget");
7327 emitcode ("pop", "b");
7331 emitcode ("anl", "a,#0x%02x", (unsigned char)
7332 ((unsigned char) (0xFF << (blen + bstr)) |
7333 (unsigned char) (0xFF >> (8 - bstr))));
7334 emitcode ("orl", "a,b");
7335 if (p_type == GPOINTER)
7336 emitcode ("pop", "b");
7343 emitcode ("mov", "@%s,a", rname);
7347 emitcode ("movx", "@dptr,a");
7351 emitcode ("lcall", "__gptrput");
7356 if (SPEC_BLEN (etype) <= 8)
7359 emitcode ("inc", "%s", rname);
7360 rLen = SPEC_BLEN (etype);
7362 /* now generate for lengths greater than one byte */
7366 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7378 emitcode ("mov", "@%s,a", rname);
7381 emitcode ("mov", "@%s,%s", rname, l);
7386 emitcode ("movx", "@dptr,a");
7391 emitcode ("lcall", "__gptrput");
7394 emitcode ("inc", "%s", rname);
7399 /* last last was not complete */
7402 /* save the byte & read byte */
7406 emitcode ("mov", "b,a");
7407 emitcode ("mov", "a,@%s", rname);
7411 emitcode ("mov", "b,a");
7412 emitcode ("movx", "a,@dptr");
7416 emitcode ("push", "b");
7417 emitcode ("push", "acc");
7418 emitcode ("lcall", "__gptrget");
7419 emitcode ("pop", "b");
7423 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7424 emitcode ("orl", "a,b");
7427 if (p_type == GPOINTER)
7428 emitcode ("pop", "b");
7434 emitcode ("mov", "@%s,a", rname);
7438 emitcode ("movx", "@dptr,a");
7442 emitcode ("lcall", "__gptrput");
7446 /*-----------------------------------------------------------------*/
7447 /* genDataPointerSet - remat pointer to data space */
7448 /*-----------------------------------------------------------------*/
7450 genDataPointerSet (operand * right,
7454 int size, offset = 0;
7455 char *l, buffer[256];
7457 aopOp (right, ic, FALSE);
7459 l = aopGet (AOP (result), 0, FALSE, TRUE);
7460 size = AOP_SIZE (right);
7464 sprintf (buffer, "(%s + %d)", l + 1, offset);
7466 sprintf (buffer, "%s", l + 1);
7467 emitcode ("mov", "%s,%s", buffer,
7468 aopGet (AOP (right), offset++, FALSE, FALSE));
7471 freeAsmop (right, NULL, ic, TRUE);
7472 freeAsmop (result, NULL, ic, TRUE);
7475 /*-----------------------------------------------------------------*/
7476 /* genNearPointerSet - emitcode for near pointer put */
7477 /*-----------------------------------------------------------------*/
7479 genNearPointerSet (operand * right,
7487 sym_link *retype, *letype;
7488 sym_link *ptype = operandType (result);
7490 retype = getSpec (operandType (right));
7491 letype = getSpec (ptype);
7492 aopOp (result, ic, FALSE);
7494 /* if the result is rematerializable &
7495 in data space & not a bit variable */
7496 if (AOP_TYPE (result) == AOP_IMMD &&
7497 DCL_TYPE (ptype) == POINTER &&
7498 !IS_BITVAR (retype) &&
7499 !IS_BITVAR (letype))
7501 genDataPointerSet (right, result, ic);
7505 /* if the value is already in a pointer register
7506 then don't need anything more */
7507 if (!AOP_INPREG (AOP (result)))
7509 /* otherwise get a free pointer register */
7511 preg = getFreePtr (ic, &aop, FALSE);
7512 emitcode ("mov", "%s,%s",
7514 aopGet (AOP (result), 0, FALSE, TRUE));
7518 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7520 aopOp (right, ic, FALSE);
7522 /* if bitfield then unpack the bits */
7523 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7524 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7527 /* we have can just get the values */
7528 int size = AOP_SIZE (right);
7533 l = aopGet (AOP (right), offset, FALSE, TRUE);
7537 emitcode ("mov", "@%s,a", rname);
7540 emitcode ("mov", "@%s,%s", rname, l);
7542 emitcode ("inc", "%s", rname);
7547 /* now some housekeeping stuff */
7548 if (aop) /* we had to allocate for this iCode */
7550 if (pi) aopPut (AOP (result),rname,0);
7551 freeAsmop (NULL, aop, ic, TRUE);
7555 /* we did not allocate which means left
7556 already in a pointer register, then
7557 if size > 0 && this could be used again
7558 we have to point it back to where it
7560 if ((AOP_SIZE (right) > 1 &&
7561 !OP_SYMBOL (result)->remat &&
7562 (OP_SYMBOL (result)->liveTo > ic->seq ||
7566 int size = AOP_SIZE (right) - 1;
7568 emitcode ("dec", "%s", rname);
7573 if (pi) pi->generated = 1;
7574 freeAsmop (result, NULL, ic, TRUE);
7575 freeAsmop (right, NULL, ic, TRUE);
7578 /*-----------------------------------------------------------------*/
7579 /* genPagedPointerSet - emitcode for Paged pointer put */
7580 /*-----------------------------------------------------------------*/
7582 genPagedPointerSet (operand * right,
7590 sym_link *retype, *letype;
7592 retype = getSpec (operandType (right));
7593 letype = getSpec (operandType (result));
7595 aopOp (result, ic, FALSE);
7597 /* if the value is already in a pointer register
7598 then don't need anything more */
7599 if (!AOP_INPREG (AOP (result)))
7601 /* otherwise get a free pointer register */
7603 preg = getFreePtr (ic, &aop, FALSE);
7604 emitcode ("mov", "%s,%s",
7606 aopGet (AOP (result), 0, FALSE, TRUE));
7610 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7612 aopOp (right, ic, FALSE);
7614 /* if bitfield then unpack the bits */
7615 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7616 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7619 /* we have can just get the values */
7620 int size = AOP_SIZE (right);
7625 l = aopGet (AOP (right), offset, FALSE, TRUE);
7628 emitcode ("movx", "@%s,a", rname);
7631 emitcode ("inc", "%s", rname);
7637 /* now some housekeeping stuff */
7638 if (aop) /* we had to allocate for this iCode */
7640 if (pi) aopPut (AOP (result),rname,0);
7641 freeAsmop (NULL, aop, ic, TRUE);
7645 /* we did not allocate which means left
7646 already in a pointer register, then
7647 if size > 0 && this could be used again
7648 we have to point it back to where it
7650 if (AOP_SIZE (right) > 1 &&
7651 !OP_SYMBOL (result)->remat &&
7652 (OP_SYMBOL (result)->liveTo > ic->seq ||
7655 int size = AOP_SIZE (right) - 1;
7657 emitcode ("dec", "%s", rname);
7662 if (pi) pi->generated = 1;
7663 freeAsmop (result, NULL, ic, TRUE);
7664 freeAsmop (right, NULL, ic, TRUE);
7669 /*-----------------------------------------------------------------*/
7670 /* genFarPointerSet - set value from far space */
7671 /*-----------------------------------------------------------------*/
7673 genFarPointerSet (operand * right,
7674 operand * result, iCode * ic, iCode * pi)
7677 sym_link *retype = getSpec (operandType (right));
7678 sym_link *letype = getSpec (operandType (result));
7679 aopOp (result, ic, FALSE);
7681 /* if the operand is already in dptr
7682 then we do nothing else we move the value to dptr */
7683 if (AOP_TYPE (result) != AOP_STR)
7685 /* if this is remateriazable */
7686 if (AOP_TYPE (result) == AOP_IMMD)
7687 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7689 { /* we need to get it byte by byte */
7690 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7691 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7694 /* so dptr know contains the address */
7695 aopOp (right, ic, FALSE);
7697 /* if bit then unpack */
7698 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7699 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7702 size = AOP_SIZE (right);
7707 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7709 emitcode ("movx", "@dptr,a");
7711 emitcode ("inc", "dptr");
7714 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7715 aopPut (AOP(result),"dpl",0);
7716 aopPut (AOP(result),"dph",1);
7719 freeAsmop (result, NULL, ic, TRUE);
7720 freeAsmop (right, NULL, ic, TRUE);
7723 /*-----------------------------------------------------------------*/
7724 /* genGenPointerSet - set value from generic pointer space */
7725 /*-----------------------------------------------------------------*/
7727 genGenPointerSet (operand * right,
7728 operand * result, iCode * ic, iCode * pi)
7731 sym_link *retype = getSpec (operandType (right));
7732 sym_link *letype = getSpec (operandType (result));
7734 aopOp (result, ic, FALSE);
7736 /* if the operand is already in dptr
7737 then we do nothing else we move the value to dptr */
7738 if (AOP_TYPE (result) != AOP_STR)
7740 /* if this is remateriazable */
7741 if (AOP_TYPE (result) == AOP_IMMD)
7743 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7744 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7747 { /* we need to get it byte by byte */
7748 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7749 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7750 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7753 /* so dptr know contains the address */
7754 aopOp (right, ic, FALSE);
7756 /* if bit then unpack */
7757 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7758 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7761 size = AOP_SIZE (right);
7766 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7768 emitcode ("lcall", "__gptrput");
7770 emitcode ("inc", "dptr");
7774 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7775 aopPut (AOP(result),"dpl",0);
7776 aopPut (AOP(result),"dph",1);
7779 freeAsmop (result, NULL, ic, TRUE);
7780 freeAsmop (right, NULL, ic, TRUE);
7783 /*-----------------------------------------------------------------*/
7784 /* genPointerSet - stores the value into a pointer location */
7785 /*-----------------------------------------------------------------*/
7787 genPointerSet (iCode * ic, iCode *pi)
7789 operand *right, *result;
7790 sym_link *type, *etype;
7793 right = IC_RIGHT (ic);
7794 result = IC_RESULT (ic);
7796 /* depending on the type of pointer we need to
7797 move it to the correct pointer register */
7798 type = operandType (result);
7799 etype = getSpec (type);
7800 /* if left is of type of pointer then it is simple */
7801 if (IS_PTR (type) && !IS_FUNC (type->next))
7803 p_type = DCL_TYPE (type);
7807 /* we have to go by the storage class */
7808 p_type = PTR_TYPE (SPEC_OCLS (etype));
7811 /* now that we have the pointer type we assign
7812 the pointer values */
7818 genNearPointerSet (right, result, ic, pi);
7822 genPagedPointerSet (right, result, ic, pi);
7826 genFarPointerSet (right, result, ic, pi);
7830 genGenPointerSet (right, result, ic, pi);
7836 /*-----------------------------------------------------------------*/
7837 /* genIfx - generate code for Ifx statement */
7838 /*-----------------------------------------------------------------*/
7840 genIfx (iCode * ic, iCode * popIc)
7842 operand *cond = IC_COND (ic);
7845 aopOp (cond, ic, FALSE);
7847 /* get the value into acc */
7848 if (AOP_TYPE (cond) != AOP_CRY)
7852 /* the result is now in the accumulator */
7853 freeAsmop (cond, NULL, ic, TRUE);
7855 /* if there was something to be popped then do it */
7859 /* if the condition is a bit variable */
7860 if (isbit && IS_ITEMP (cond) &&
7862 genIfxJump (ic, SPIL_LOC (cond)->rname);
7863 else if (isbit && !IS_ITEMP (cond))
7864 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7866 genIfxJump (ic, "a");
7871 /*-----------------------------------------------------------------*/
7872 /* genAddrOf - generates code for address of */
7873 /*-----------------------------------------------------------------*/
7875 genAddrOf (iCode * ic)
7877 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7880 aopOp (IC_RESULT (ic), ic, FALSE);
7882 /* if the operand is on the stack then we
7883 need to get the stack offset of this
7887 /* if it has an offset then we need to compute
7891 emitcode ("mov", "a,_bp");
7892 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7893 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7897 /* we can just move _bp */
7898 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7900 /* fill the result with zero */
7901 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7906 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7912 /* object not on stack then we need the name */
7913 size = AOP_SIZE (IC_RESULT (ic));
7918 char s[SDCC_NAME_MAX];
7920 sprintf (s, "#(%s >> %d)",
7924 sprintf (s, "#%s", sym->rname);
7925 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7929 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7933 /*-----------------------------------------------------------------*/
7934 /* genFarFarAssign - assignment when both are in far space */
7935 /*-----------------------------------------------------------------*/
7937 genFarFarAssign (operand * result, operand * right, iCode * ic)
7939 int size = AOP_SIZE (right);
7942 /* first push the right side on to the stack */
7945 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7947 emitcode ("push", "acc");
7950 freeAsmop (right, NULL, ic, FALSE);
7951 /* now assign DPTR to result */
7952 aopOp (result, ic, FALSE);
7953 size = AOP_SIZE (result);
7956 emitcode ("pop", "acc");
7957 aopPut (AOP (result), "a", --offset);
7959 freeAsmop (result, NULL, ic, FALSE);
7963 /*-----------------------------------------------------------------*/
7964 /* genAssign - generate code for assignment */
7965 /*-----------------------------------------------------------------*/
7967 genAssign (iCode * ic)
7969 operand *result, *right;
7971 unsigned long lit = 0L;
7973 result = IC_RESULT (ic);
7974 right = IC_RIGHT (ic);
7976 /* if they are the same */
7977 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7980 aopOp (right, ic, FALSE);
7982 /* special case both in far space */
7983 if (AOP_TYPE (right) == AOP_DPTR &&
7984 IS_TRUE_SYMOP (result) &&
7985 isOperandInFarSpace (result))
7988 genFarFarAssign (result, right, ic);
7992 aopOp (result, ic, TRUE);
7994 /* if they are the same registers */
7995 if (sameRegs (AOP (right), AOP (result)))
7998 /* if the result is a bit */
7999 if (AOP_TYPE (result) == AOP_CRY)
8002 /* if the right size is a literal then
8003 we know what the value is */
8004 if (AOP_TYPE (right) == AOP_LIT)
8006 if (((int) operandLitValue (right)))
8007 aopPut (AOP (result), one, 0);
8009 aopPut (AOP (result), zero, 0);
8013 /* the right is also a bit variable */
8014 if (AOP_TYPE (right) == AOP_CRY)
8016 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8017 aopPut (AOP (result), "c", 0);
8023 aopPut (AOP (result), "a", 0);
8027 /* bit variables done */
8029 size = AOP_SIZE (result);
8031 if (AOP_TYPE (right) == AOP_LIT)
8032 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8034 (AOP_TYPE (result) != AOP_REG) &&
8035 (AOP_TYPE (right) == AOP_LIT) &&
8036 !IS_FLOAT (operandType (right)) &&
8039 emitcode ("clr", "a");
8042 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8043 aopPut (AOP (result), "a", size);
8045 aopPut (AOP (result),
8046 aopGet (AOP (right), size, FALSE, FALSE),
8054 aopPut (AOP (result),
8055 aopGet (AOP (right), offset, FALSE, FALSE),
8062 freeAsmop (right, NULL, ic, TRUE);
8063 freeAsmop (result, NULL, ic, TRUE);
8066 /*-----------------------------------------------------------------*/
8067 /* genJumpTab - genrates code for jump table */
8068 /*-----------------------------------------------------------------*/
8070 genJumpTab (iCode * ic)
8075 aopOp (IC_JTCOND (ic), ic, FALSE);
8076 /* get the condition into accumulator */
8077 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8079 /* multiply by three */
8080 emitcode ("add", "a,acc");
8081 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8082 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8084 jtab = newiTempLabel (NULL);
8085 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8086 emitcode ("jmp", "@a+dptr");
8087 emitcode ("", "%05d$:", jtab->key + 100);
8088 /* now generate the jump labels */
8089 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8090 jtab = setNextItem (IC_JTLABELS (ic)))
8091 emitcode ("ljmp", "%05d$", jtab->key + 100);
8095 /*-----------------------------------------------------------------*/
8096 /* genCast - gen code for casting */
8097 /*-----------------------------------------------------------------*/
8099 genCast (iCode * ic)
8101 operand *result = IC_RESULT (ic);
8102 sym_link *ctype = operandType (IC_LEFT (ic));
8103 sym_link *rtype = operandType (IC_RIGHT (ic));
8104 operand *right = IC_RIGHT (ic);
8107 /* if they are equivalent then do nothing */
8108 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8111 aopOp (right, ic, FALSE);
8112 aopOp (result, ic, FALSE);
8114 /* if the result is a bit */
8115 if (AOP_TYPE (result) == AOP_CRY)
8117 /* if the right size is a literal then
8118 we know what the value is */
8119 if (AOP_TYPE (right) == AOP_LIT)
8121 if (((int) operandLitValue (right)))
8122 aopPut (AOP (result), one, 0);
8124 aopPut (AOP (result), zero, 0);
8129 /* the right is also a bit variable */
8130 if (AOP_TYPE (right) == AOP_CRY)
8132 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8133 aopPut (AOP (result), "c", 0);
8139 aopPut (AOP (result), "a", 0);
8143 /* if they are the same size : or less */
8144 if (AOP_SIZE (result) <= AOP_SIZE (right))
8147 /* if they are in the same place */
8148 if (sameRegs (AOP (right), AOP (result)))
8151 /* if they in different places then copy */
8152 size = AOP_SIZE (result);
8156 aopPut (AOP (result),
8157 aopGet (AOP (right), offset, FALSE, FALSE),
8165 /* if the result is of type pointer */
8170 sym_link *type = operandType (right);
8171 sym_link *etype = getSpec (type);
8173 /* pointer to generic pointer */
8174 if (IS_GENPTR (ctype))
8179 p_type = DCL_TYPE (type);
8182 /* we have to go by the storage class */
8183 p_type = PTR_TYPE (SPEC_OCLS (etype));
8186 /* the first two bytes are known */
8187 size = GPTRSIZE - 1;
8191 aopPut (AOP (result),
8192 aopGet (AOP (right), offset, FALSE, FALSE),
8196 /* the last byte depending on type */
8214 /* this should never happen */
8215 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8216 "got unknown pointer type");
8219 aopPut (AOP (result), l, GPTRSIZE - 1);
8223 /* just copy the pointers */
8224 size = AOP_SIZE (result);
8228 aopPut (AOP (result),
8229 aopGet (AOP (right), offset, FALSE, FALSE),
8236 /* so we now know that the size of destination is greater
8237 than the size of the source */
8238 /* we move to result for the size of source */
8239 size = AOP_SIZE (right);
8243 aopPut (AOP (result),
8244 aopGet (AOP (right), offset, FALSE, FALSE),
8249 /* now depending on the sign of the source && destination */
8250 size = AOP_SIZE (result) - AOP_SIZE (right);
8251 /* if unsigned or not an integral type */
8252 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8255 aopPut (AOP (result), zero, offset++);
8259 /* we need to extend the sign :{ */
8260 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8263 emitcode ("rlc", "a");
8264 emitcode ("subb", "a,acc");
8266 aopPut (AOP (result), "a", offset++);
8269 /* we are done hurray !!!! */
8272 freeAsmop (right, NULL, ic, TRUE);
8273 freeAsmop (result, NULL, ic, TRUE);
8277 /*-----------------------------------------------------------------*/
8278 /* genDjnz - generate decrement & jump if not zero instrucion */
8279 /*-----------------------------------------------------------------*/
8281 genDjnz (iCode * ic, iCode * ifx)
8287 /* if the if condition has a false label
8288 then we cannot save */
8292 /* if the minus is not of the form
8294 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8295 !IS_OP_LITERAL (IC_RIGHT (ic)))
8298 if (operandLitValue (IC_RIGHT (ic)) != 1)
8301 /* if the size of this greater than one then no
8303 if (getSize (operandType (IC_RESULT (ic))) > 1)
8306 /* otherwise we can save BIG */
8307 lbl = newiTempLabel (NULL);
8308 lbl1 = newiTempLabel (NULL);
8310 aopOp (IC_RESULT (ic), ic, FALSE);
8312 if (AOP_NEEDSACC(IC_RESULT(ic)))
8314 /* If the result is accessed indirectly via
8315 * the accumulator, we must explicitly write
8316 * it back after the decrement.
8318 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8320 if (strcmp(rByte, "a"))
8322 /* Something is hopelessly wrong */
8323 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8324 __FILE__, __LINE__);
8325 /* We can just give up; the generated code will be inefficient,
8328 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8331 emitcode ("dec", "%s", rByte);
8332 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8333 emitcode ("jnz", "%05d$", lbl->key + 100);
8335 else if (IS_AOP_PREG (IC_RESULT (ic)))
8337 emitcode ("dec", "%s",
8338 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8339 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8340 emitcode ("jnz", "%05d$", lbl->key + 100);
8344 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8347 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8348 emitcode ("", "%05d$:", lbl->key + 100);
8349 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8350 emitcode ("", "%05d$:", lbl1->key + 100);
8352 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8357 /*-----------------------------------------------------------------*/
8358 /* genReceive - generate code for a receive iCode */
8359 /*-----------------------------------------------------------------*/
8361 genReceive (iCode * ic)
8363 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8364 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8365 IS_TRUE_SYMOP (IC_RESULT (ic))))
8368 int size = getSize (operandType (IC_RESULT (ic)));
8369 int offset = fReturnSizeMCS51 - size;
8372 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8373 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8376 aopOp (IC_RESULT (ic), ic, FALSE);
8377 size = AOP_SIZE (IC_RESULT (ic));
8381 emitcode ("pop", "acc");
8382 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8389 aopOp (IC_RESULT (ic), ic, FALSE);
8391 assignResultValue (IC_RESULT (ic));
8394 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8397 /*-----------------------------------------------------------------*/
8398 /* gen51Code - generate code for 8051 based controllers */
8399 /*-----------------------------------------------------------------*/
8401 gen51Code (iCode * lic)
8406 lineHead = lineCurr = NULL;
8408 /* print the allocation information */
8410 printAllocInfo (currFunc, codeOutFile);
8411 /* if debug information required */
8412 /* if (options.debug && currFunc) { */
8415 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8417 if (IS_STATIC (currFunc->etype))
8418 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8420 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8423 /* stack pointer name */
8424 if (options.useXstack)
8430 for (ic = lic; ic; ic = ic->next)
8433 if (cln != ic->lineno)
8438 emitcode ("", "C$%s$%d$%d$%d ==.",
8439 FileBaseName (ic->filename), ic->lineno,
8440 ic->level, ic->block);
8443 emitcode (";", "%s %d", ic->filename, ic->lineno);
8446 /* if the result is marked as
8447 spilt and rematerializable or code for
8448 this has already been generated then
8450 if (resultRemat (ic) || ic->generated)
8453 /* depending on the operation */
8473 /* IPOP happens only when trying to restore a
8474 spilt live range, if there is an ifx statement
8475 following this pop then the if statement might
8476 be using some of the registers being popped which
8477 would destory the contents of the register so
8478 we need to check for this condition and handle it */
8480 ic->next->op == IFX &&
8481 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8482 genIfx (ic->next, ic);
8500 genEndFunction (ic);
8520 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8537 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8541 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8548 /* note these two are xlated by algebraic equivalence
8549 during parsing SDCC.y */
8550 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8551 "got '>=' or '<=' shouldn't have come here");
8555 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8567 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8571 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8575 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8602 case GET_VALUE_AT_ADDRESS:
8603 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8607 if (POINTER_SET (ic))
8608 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8634 addSet (&_G.sendSet, ic);
8643 /* now we are ready to call the
8644 peep hole optimizer */
8645 if (!options.nopeep)
8646 peepHole (&lineHead);
8648 /* now do the actual printing */
8649 printLine (lineHead, codeOutFile);