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 or don't need to be then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1449 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1452 /* find the registers in use at this time
1453 and push them away to safety */
1454 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1458 if (options.useXstack)
1460 if (bitVectBitValue (rsave, R0_IDX))
1461 emitcode ("mov", "b,r0");
1462 emitcode ("mov", "r0,%s", spname);
1463 for (i = 0; i < mcs51_nRegs; i++)
1465 if (bitVectBitValue (rsave, i))
1468 emitcode ("mov", "a,b");
1470 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1471 emitcode ("movx", "@r0,a");
1472 emitcode ("inc", "r0");
1475 emitcode ("mov", "%s,r0", spname);
1476 if (bitVectBitValue (rsave, R0_IDX))
1477 emitcode ("mov", "r0,b");
1480 for (i = 0; i < mcs51_nRegs; i++)
1482 if (bitVectBitValue (rsave, i))
1483 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1486 detype = getSpec (operandType (IC_LEFT (ic)));
1489 /*-----------------------------------------------------------------*/
1490 /* unsaveRegisters - pop the pushed registers */
1491 /*-----------------------------------------------------------------*/
1493 unsaveRegisters (iCode * ic)
1497 /* find the registers in use at this time
1498 and push them away to safety */
1499 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1502 if (options.useXstack)
1504 emitcode ("mov", "r0,%s", spname);
1505 for (i = mcs51_nRegs; i >= 0; i--)
1507 if (bitVectBitValue (rsave, i))
1509 emitcode ("dec", "r0");
1510 emitcode ("movx", "a,@r0");
1512 emitcode ("mov", "b,a");
1514 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1518 emitcode ("mov", "%s,r0", spname);
1519 if (bitVectBitValue (rsave, R0_IDX))
1520 emitcode ("mov", "r0,b");
1523 for (i = mcs51_nRegs; i >= 0; i--)
1525 if (bitVectBitValue (rsave, i))
1526 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1532 /*-----------------------------------------------------------------*/
1534 /*-----------------------------------------------------------------*/
1536 pushSide (operand * oper, int size)
1541 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1542 if (AOP_TYPE (oper) != AOP_REG &&
1543 AOP_TYPE (oper) != AOP_DIR &&
1546 emitcode ("mov", "a,%s", l);
1547 emitcode ("push", "acc");
1550 emitcode ("push", "%s", l);
1554 /*-----------------------------------------------------------------*/
1555 /* assignResultValue - */
1556 /*-----------------------------------------------------------------*/
1558 assignResultValue (operand * oper)
1561 int size = AOP_SIZE (oper);
1564 aopPut (AOP (oper), fReturn[offset], offset);
1570 /*-----------------------------------------------------------------*/
1571 /* genXpush - pushes onto the external stack */
1572 /*-----------------------------------------------------------------*/
1574 genXpush (iCode * ic)
1576 asmop *aop = newAsmop (0);
1578 int size, offset = 0;
1580 aopOp (IC_LEFT (ic), ic, FALSE);
1581 r = getFreePtr (ic, &aop, FALSE);
1584 emitcode ("mov", "%s,_spx", r->name);
1586 size = AOP_SIZE (IC_LEFT (ic));
1590 char *l = aopGet (AOP (IC_LEFT (ic)),
1591 offset++, FALSE, FALSE);
1593 emitcode ("movx", "@%s,a", r->name);
1594 emitcode ("inc", "%s", r->name);
1599 emitcode ("mov", "_spx,%s", r->name);
1601 freeAsmop (NULL, aop, ic, TRUE);
1602 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1605 /*-----------------------------------------------------------------*/
1606 /* genIpush - genrate code for pushing this gets a little complex */
1607 /*-----------------------------------------------------------------*/
1609 genIpush (iCode * ic)
1611 int size, offset = 0;
1614 /* if this is not a parm push : ie. it is spill push
1615 and spill push is always done on the local stack */
1619 /* and the item is spilt then do nothing */
1620 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1623 aopOp (IC_LEFT (ic), ic, FALSE);
1624 size = AOP_SIZE (IC_LEFT (ic));
1625 /* push it on the stack */
1628 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1634 emitcode ("push", "%s", l);
1639 /* this is a paramter push: in this case we call
1640 the routine to find the call and save those
1641 registers that need to be saved */
1644 /* if use external stack then call the external
1645 stack pushing routine */
1646 if (options.useXstack)
1652 /* then do the push */
1653 aopOp (IC_LEFT (ic), ic, FALSE);
1656 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1657 size = AOP_SIZE (IC_LEFT (ic));
1661 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1662 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1663 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1666 emitcode ("mov", "a,%s", l);
1667 emitcode ("push", "acc");
1670 emitcode ("push", "%s", l);
1673 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1676 /*-----------------------------------------------------------------*/
1677 /* genIpop - recover the registers: can happen only for spilling */
1678 /*-----------------------------------------------------------------*/
1680 genIpop (iCode * ic)
1685 /* if the temp was not pushed then */
1686 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1689 aopOp (IC_LEFT (ic), ic, FALSE);
1690 size = AOP_SIZE (IC_LEFT (ic));
1691 offset = (size - 1);
1693 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1696 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1699 /*-----------------------------------------------------------------*/
1700 /* unsaveRBank - restores the resgister bank from stack */
1701 /*-----------------------------------------------------------------*/
1703 unsaveRBank (int bank, iCode * ic, bool popPsw)
1709 if (options.useXstack)
1713 /* Assume r0 is available for use. */
1714 r = mcs51_regWithIdx (R0_IDX);;
1719 r = getFreePtr (ic, &aop, FALSE);
1721 emitcode ("mov", "%s,_spx", r->name);
1726 if (options.useXstack)
1728 emitcode ("movx", "a,@%s", r->name);
1729 emitcode ("mov", "psw,a");
1730 emitcode ("dec", "%s", r->name);
1734 emitcode ("pop", "psw");
1738 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1740 if (options.useXstack)
1742 emitcode ("movx", "a,@%s", r->name);
1743 emitcode ("mov", "(%s+%d),a",
1744 regs8051[i].base, 8 * bank + regs8051[i].offset);
1745 emitcode ("dec", "%s", r->name);
1749 emitcode ("pop", "(%s+%d)",
1750 regs8051[i].base, 8 * bank + regs8051[i].offset);
1753 if (options.useXstack)
1755 emitcode ("mov", "_spx,%s", r->name);
1760 freeAsmop (NULL, aop, ic, TRUE);
1764 /*-----------------------------------------------------------------*/
1765 /* saveRBank - saves an entire register bank on the stack */
1766 /*-----------------------------------------------------------------*/
1768 saveRBank (int bank, iCode * ic, bool pushPsw)
1774 if (options.useXstack)
1778 /* Assume r0 is available for use. */
1779 r = mcs51_regWithIdx (R0_IDX);;
1784 r = getFreePtr (ic, &aop, FALSE);
1786 emitcode ("mov", "%s,_spx", r->name);
1789 for (i = 0; i < mcs51_nRegs; i++)
1791 if (options.useXstack)
1793 emitcode ("inc", "%s", r->name);
1794 emitcode ("mov", "a,(%s+%d)",
1795 regs8051[i].base, 8 * bank + regs8051[i].offset);
1796 emitcode ("movx", "@%s,a", r->name);
1799 emitcode ("push", "(%s+%d)",
1800 regs8051[i].base, 8 * bank + regs8051[i].offset);
1805 if (options.useXstack)
1807 emitcode ("mov", "a,psw");
1808 emitcode ("movx", "@%s,a", r->name);
1809 emitcode ("inc", "%s", r->name);
1810 emitcode ("mov", "_spx,%s", r->name);
1815 emitcode ("push", "psw");
1818 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1823 freeAsmop (NULL, aop, ic, TRUE);
1832 /*-----------------------------------------------------------------*/
1833 /* genCall - generates a call statement */
1834 /*-----------------------------------------------------------------*/
1836 genCall (iCode * ic)
1839 bool restoreBank = FALSE;
1840 bool swapBanks = FALSE;
1842 /* if send set is not empty the assign */
1847 for (sic = setFirstItem (_G.sendSet); sic;
1848 sic = setNextItem (_G.sendSet))
1850 int size, offset = 0;
1851 aopOp (IC_LEFT (sic), sic, FALSE);
1852 size = AOP_SIZE (IC_LEFT (sic));
1855 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1857 if (strcmp (l, fReturn[offset]))
1858 emitcode ("mov", "%s,%s",
1863 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1868 /* if we are calling a not _naked function that is not using
1869 the same register bank then we need to save the
1870 destination registers on the stack */
1871 detype = getSpec (operandType (IC_LEFT (ic)));
1872 if (detype && !SPEC_NAKED(detype) &&
1873 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1874 IS_ISR (currFunc->etype))
1878 /* This is unexpected; the bank should have been saved in
1881 saveRBank (SPEC_BANK (detype), ic, FALSE);
1887 /* if caller saves & we have not saved then */
1893 emitcode ("mov", "psw,#0x%02x",
1894 ((SPEC_BANK(detype)) << 3) & 0xff);
1898 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1899 OP_SYMBOL (IC_LEFT (ic))->rname :
1900 OP_SYMBOL (IC_LEFT (ic))->name));
1904 emitcode ("mov", "psw,#0x%02x",
1905 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1908 /* if we need assign a result value */
1909 if ((IS_ITEMP (IC_RESULT (ic)) &&
1910 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1911 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1912 IS_TRUE_SYMOP (IC_RESULT (ic)))
1916 aopOp (IC_RESULT (ic), ic, FALSE);
1919 assignResultValue (IC_RESULT (ic));
1921 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1924 /* adjust the stack for parameters if
1929 if (ic->parmBytes > 3)
1931 emitcode ("mov", "a,%s", spname);
1932 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1933 emitcode ("mov", "%s,a", spname);
1936 for (i = 0; i < ic->parmBytes; i++)
1937 emitcode ("dec", "%s", spname);
1940 /* if we hade saved some registers then unsave them */
1941 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1942 unsaveRegisters (ic);
1944 /* if register bank was saved then pop them */
1946 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1949 /*-----------------------------------------------------------------*/
1950 /* genPcall - generates a call by pointer statement */
1951 /*-----------------------------------------------------------------*/
1953 genPcall (iCode * ic)
1956 symbol *rlbl = newiTempLabel (NULL);
1959 /* if caller saves & we have not saved then */
1963 /* if we are calling a function that is not using
1964 the same register bank then we need to save the
1965 destination registers on the stack */
1966 detype = getSpec (operandType (IC_LEFT (ic)));
1968 IS_ISR (currFunc->etype) &&
1969 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1970 saveRBank (SPEC_BANK (detype), ic, TRUE);
1973 /* push the return address on to the stack */
1974 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1975 emitcode ("push", "acc");
1976 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1977 emitcode ("push", "acc");
1979 /* now push the calling address */
1980 aopOp (IC_LEFT (ic), ic, FALSE);
1982 pushSide (IC_LEFT (ic), FPTRSIZE);
1984 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1986 /* if send set is not empty the assign */
1991 for (sic = setFirstItem (_G.sendSet); sic;
1992 sic = setNextItem (_G.sendSet))
1994 int size, offset = 0;
1995 aopOp (IC_LEFT (sic), sic, FALSE);
1996 size = AOP_SIZE (IC_LEFT (sic));
1999 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2001 if (strcmp (l, fReturn[offset]))
2002 emitcode ("mov", "%s,%s",
2007 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2012 emitcode ("ret", "");
2013 emitcode ("", "%05d$:", (rlbl->key + 100));
2016 /* if we need assign a result value */
2017 if ((IS_ITEMP (IC_RESULT (ic)) &&
2018 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2019 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2020 IS_TRUE_SYMOP (IC_RESULT (ic)))
2024 aopOp (IC_RESULT (ic), ic, FALSE);
2027 assignResultValue (IC_RESULT (ic));
2029 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2032 /* adjust the stack for parameters if
2037 if (ic->parmBytes > 3)
2039 emitcode ("mov", "a,%s", spname);
2040 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2041 emitcode ("mov", "%s,a", spname);
2044 for (i = 0; i < ic->parmBytes; i++)
2045 emitcode ("dec", "%s", spname);
2049 /* if register bank was saved then unsave them */
2051 (SPEC_BANK (currFunc->etype) !=
2052 SPEC_BANK (detype)))
2053 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2055 /* if we hade saved some registers then
2058 unsaveRegisters (ic);
2062 /*-----------------------------------------------------------------*/
2063 /* resultRemat - result is rematerializable */
2064 /*-----------------------------------------------------------------*/
2066 resultRemat (iCode * ic)
2068 if (SKIP_IC (ic) || ic->op == IFX)
2071 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2073 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2074 if (sym->remat && !POINTER_SET (ic))
2081 #if defined(__BORLANDC__) || defined(_MSC_VER)
2082 #define STRCASECMP stricmp
2084 #define STRCASECMP strcasecmp
2087 /*-----------------------------------------------------------------*/
2088 /* inExcludeList - return 1 if the string is in exclude Reg list */
2089 /*-----------------------------------------------------------------*/
2091 inExcludeList (char *s)
2095 if (options.excludeRegs[i] &&
2096 STRCASECMP (options.excludeRegs[i], "none") == 0)
2099 for (i = 0; options.excludeRegs[i]; i++)
2101 if (options.excludeRegs[i] &&
2102 STRCASECMP (s, options.excludeRegs[i]) == 0)
2108 /*-----------------------------------------------------------------*/
2109 /* genFunction - generated code for function entry */
2110 /*-----------------------------------------------------------------*/
2112 genFunction (iCode * ic)
2116 bool switchedPSW = FALSE;
2119 /* create the function header */
2120 emitcode (";", "-----------------------------------------");
2121 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2122 emitcode (";", "-----------------------------------------");
2124 emitcode ("", "%s:", sym->rname);
2125 fetype = getSpec (operandType (IC_LEFT (ic)));
2127 if (SPEC_NAKED(fetype))
2129 emitcode(";", "naked function: no prologue.");
2133 /* if critical function then turn interrupts off */
2134 if (SPEC_CRTCL (fetype))
2135 emitcode ("clr", "ea");
2137 /* here we need to generate the equates for the
2138 register bank if required */
2139 if (SPEC_BANK (fetype) != rbank)
2143 rbank = SPEC_BANK (fetype);
2144 for (i = 0; i < mcs51_nRegs; i++)
2146 if (strcmp (regs8051[i].base, "0") == 0)
2147 emitcode ("", "%s = 0x%02x",
2149 8 * rbank + regs8051[i].offset);
2151 emitcode ("", "%s = %s + 0x%02x",
2154 8 * rbank + regs8051[i].offset);
2158 /* if this is an interrupt service routine then
2159 save acc, b, dpl, dph */
2160 if (IS_ISR (sym->etype))
2163 if (!inExcludeList ("acc"))
2164 emitcode ("push", "acc");
2165 if (!inExcludeList ("b"))
2166 emitcode ("push", "b");
2167 if (!inExcludeList ("dpl"))
2168 emitcode ("push", "dpl");
2169 if (!inExcludeList ("dph"))
2170 emitcode ("push", "dph");
2171 /* if this isr has no bank i.e. is going to
2172 run with bank 0 , then we need to save more
2174 if (!SPEC_BANK (sym->etype))
2177 /* if this function does not call any other
2178 function then we can be economical and
2179 save only those registers that are used */
2184 /* if any registers used */
2187 /* save the registers used */
2188 for (i = 0; i < sym->regsUsed->size; i++)
2190 if (bitVectBitValue (sym->regsUsed, i) ||
2191 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2192 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2199 /* this function has a function call cannot
2200 determines register usage so we will have to push the
2202 saveRBank (0, ic, FALSE);
2207 /* This ISR uses a non-zero bank.
2209 * We assume that the bank is available for our
2212 * However, if this ISR calls a function which uses some
2213 * other bank, we must save that bank entirely.
2215 unsigned long banksToSave = 0;
2220 #define MAX_REGISTER_BANKS 4
2225 for (i = ic; i; i = i->next)
2227 if (i->op == ENDFUNCTION)
2229 /* we got to the end OK. */
2237 detype = getSpec(operandType (IC_LEFT(i)));
2239 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2241 /* Mark this bank for saving. */
2242 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2244 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2248 banksToSave |= (1 << SPEC_BANK(detype));
2251 /* And note that we don't need to do it in
2259 /* This is a mess; we have no idea what
2260 * register bank the called function might
2263 * The only thing I can think of to do is
2264 * throw a warning and hope.
2266 werror(W_FUNCPTR_IN_USING_ISR);
2270 if (banksToSave && options.useXstack)
2272 /* Since we aren't passing it an ic,
2273 * saveRBank will assume r0 is available to abuse.
2275 * So switch to our (trashable) bank now, so
2276 * the caller's R0 isn't trashed.
2278 emitcode ("push", "psw");
2279 emitcode ("mov", "psw,#0x%02x",
2280 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2284 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2286 if (banksToSave & (1 << ix))
2288 saveRBank(ix, NULL, FALSE);
2292 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2297 /* if callee-save to be used for this function
2298 then save the registers being used in this function */
2299 if (sym->calleeSave)
2303 /* if any registers used */
2306 /* save the registers used */
2307 for (i = 0; i < sym->regsUsed->size; i++)
2309 if (bitVectBitValue (sym->regsUsed, i) ||
2310 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2312 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2320 /* set the register bank to the desired value */
2321 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2324 emitcode ("push", "psw");
2325 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2328 if (IS_RENT (sym->etype) || options.stackAuto)
2331 if (options.useXstack)
2333 emitcode ("mov", "r0,%s", spname);
2334 emitcode ("mov", "a,_bp");
2335 emitcode ("movx", "@r0,a");
2336 emitcode ("inc", "%s", spname);
2340 /* set up the stack */
2341 emitcode ("push", "_bp"); /* save the callers stack */
2343 emitcode ("mov", "_bp,%s", spname);
2346 /* adjust the stack for the function */
2352 werror (W_STACK_OVERFLOW, sym->name);
2354 if (i > 3 && sym->recvSize < 4)
2357 emitcode ("mov", "a,sp");
2358 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2359 emitcode ("mov", "sp,a");
2364 emitcode ("inc", "sp");
2370 emitcode ("mov", "a,_spx");
2371 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2372 emitcode ("mov", "_spx,a");
2377 /*-----------------------------------------------------------------*/
2378 /* genEndFunction - generates epilogue for functions */
2379 /*-----------------------------------------------------------------*/
2381 genEndFunction (iCode * ic)
2383 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2385 if (SPEC_NAKED(sym->etype))
2387 emitcode(";", "naked function: no epilogue.");
2391 if (IS_RENT (sym->etype) || options.stackAuto)
2393 emitcode ("mov", "%s,_bp", spname);
2396 /* if use external stack but some variables were
2397 added to the local stack then decrement the
2399 if (options.useXstack && sym->stack)
2401 emitcode ("mov", "a,sp");
2402 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2403 emitcode ("mov", "sp,a");
2407 if ((IS_RENT (sym->etype) || options.stackAuto))
2409 if (options.useXstack)
2411 emitcode ("mov", "r0,%s", spname);
2412 emitcode ("movx", "a,@r0");
2413 emitcode ("mov", "_bp,a");
2414 emitcode ("dec", "%s", spname);
2418 emitcode ("pop", "_bp");
2422 /* restore the register bank */
2423 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2425 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2426 || !options.useXstack)
2428 /* Special case of ISR using non-zero bank with useXstack
2431 emitcode ("pop", "psw");
2435 if (IS_ISR (sym->etype))
2438 /* now we need to restore the registers */
2439 /* if this isr has no bank i.e. is going to
2440 run with bank 0 , then we need to save more
2442 if (!SPEC_BANK (sym->etype))
2444 /* if this function does not call any other
2445 function then we can be economical and
2446 save only those registers that are used */
2451 /* if any registers used */
2454 /* save the registers used */
2455 for (i = sym->regsUsed->size; i >= 0; i--)
2457 if (bitVectBitValue (sym->regsUsed, i) ||
2458 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2459 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2466 /* this function has a function call cannot
2467 determines register usage so we will have to pop the
2469 unsaveRBank (0, ic, FALSE);
2474 /* This ISR uses a non-zero bank.
2476 * Restore any register banks saved by genFunction
2479 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2482 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2484 if (savedBanks & (1 << ix))
2486 unsaveRBank(ix, NULL, FALSE);
2490 if (options.useXstack)
2492 /* Restore bank AFTER calling unsaveRBank,
2493 * since it can trash r0.
2495 emitcode ("pop", "psw");
2499 if (!inExcludeList ("dph"))
2500 emitcode ("pop", "dph");
2501 if (!inExcludeList ("dpl"))
2502 emitcode ("pop", "dpl");
2503 if (!inExcludeList ("b"))
2504 emitcode ("pop", "b");
2505 if (!inExcludeList ("acc"))
2506 emitcode ("pop", "acc");
2508 if (SPEC_CRTCL (sym->etype))
2509 emitcode ("setb", "ea");
2511 /* if debug then send end of function */
2512 /* if (options.debug && currFunc) */
2516 emitcode ("", "C$%s$%d$%d$%d ==.",
2517 FileBaseName (ic->filename), currFunc->lastLine,
2518 ic->level, ic->block);
2519 if (IS_STATIC (currFunc->etype))
2520 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2522 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2526 emitcode ("reti", "");
2530 if (SPEC_CRTCL (sym->etype))
2531 emitcode ("setb", "ea");
2533 if (sym->calleeSave)
2537 /* if any registers used */
2540 /* save the registers used */
2541 for (i = sym->regsUsed->size; i >= 0; i--)
2543 if (bitVectBitValue (sym->regsUsed, i) ||
2544 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2545 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2551 /* if debug then send end of function */
2555 emitcode ("", "C$%s$%d$%d$%d ==.",
2556 FileBaseName (ic->filename), currFunc->lastLine,
2557 ic->level, ic->block);
2558 if (IS_STATIC (currFunc->etype))
2559 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2561 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2565 emitcode ("ret", "");
2570 /*-----------------------------------------------------------------*/
2571 /* genRet - generate code for return statement */
2572 /*-----------------------------------------------------------------*/
2576 int size, offset = 0, pushed = 0;
2578 /* if we have no return value then
2579 just generate the "ret" */
2583 /* we have something to return then
2584 move the return value into place */
2585 aopOp (IC_LEFT (ic), ic, FALSE);
2586 size = AOP_SIZE (IC_LEFT (ic));
2591 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2594 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2596 emitcode ("push", "%s", l);
2601 l = aopGet (AOP (IC_LEFT (ic)), offset,
2603 if (strcmp (fReturn[offset], l))
2604 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2613 if (strcmp (fReturn[pushed], "a"))
2614 emitcode ("pop", fReturn[pushed]);
2616 emitcode ("pop", "acc");
2619 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2622 /* generate a jump to the return label
2623 if the next is not the return statement */
2624 if (!(ic->next && ic->next->op == LABEL &&
2625 IC_LABEL (ic->next) == returnLabel))
2627 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2631 /*-----------------------------------------------------------------*/
2632 /* genLabel - generates a label */
2633 /*-----------------------------------------------------------------*/
2635 genLabel (iCode * ic)
2637 /* special case never generate */
2638 if (IC_LABEL (ic) == entryLabel)
2641 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2644 /*-----------------------------------------------------------------*/
2645 /* genGoto - generates a ljmp */
2646 /*-----------------------------------------------------------------*/
2648 genGoto (iCode * ic)
2650 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2653 /*-----------------------------------------------------------------*/
2654 /* findLabelBackwards: walks back through the iCode chain looking */
2655 /* for the given label. Returns number of iCode instructions */
2656 /* between that label and given ic. */
2657 /* Returns zero if label not found. */
2658 /*-----------------------------------------------------------------*/
2660 findLabelBackwards (iCode * ic, int key)
2669 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2671 /* printf("findLabelBackwards = %d\n", count); */
2679 /*-----------------------------------------------------------------*/
2680 /* genPlusIncr :- does addition with increment if possible */
2681 /*-----------------------------------------------------------------*/
2683 genPlusIncr (iCode * ic)
2685 unsigned int icount;
2686 unsigned int size = getDataSize (IC_RESULT (ic));
2688 /* will try to generate an increment */
2689 /* if the right side is not a literal
2691 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2694 /* if the literal value of the right hand side
2695 is greater than 4 then it is not worth it */
2696 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2699 /* if increment 16 bits in register */
2700 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2708 /* If the next instruction is a goto and the goto target
2709 * is < 10 instructions previous to this, we can generate
2710 * jumps straight to that target.
2712 if (ic->next && ic->next->op == GOTO
2713 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2714 && labelRange <= 10)
2716 emitcode (";", "tail increment optimized");
2717 tlbl = IC_LABEL (ic->next);
2722 tlbl = newiTempLabel (NULL);
2725 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2726 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2727 IS_AOP_PREG (IC_RESULT (ic)))
2728 emitcode ("cjne", "%s,#0x00,%05d$"
2729 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2733 emitcode ("clr", "a");
2734 emitcode ("cjne", "a,%s,%05d$"
2735 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2739 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2742 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2743 IS_AOP_PREG (IC_RESULT (ic)))
2744 emitcode ("cjne", "%s,#0x00,%05d$"
2745 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2748 emitcode ("cjne", "a,%s,%05d$"
2749 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2752 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2756 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2757 IS_AOP_PREG (IC_RESULT (ic)))
2758 emitcode ("cjne", "%s,#0x00,%05d$"
2759 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2763 emitcode ("cjne", "a,%s,%05d$"
2764 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2767 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2772 emitcode ("", "%05d$:", tlbl->key + 100);
2777 /* if the sizes are greater than 1 then we cannot */
2778 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2779 AOP_SIZE (IC_LEFT (ic)) > 1)
2782 /* we can if the aops of the left & result match or
2783 if they are in registers and the registers are the
2785 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2790 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2791 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2792 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2798 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2807 /*-----------------------------------------------------------------*/
2808 /* outBitAcc - output a bit in acc */
2809 /*-----------------------------------------------------------------*/
2811 outBitAcc (operand * result)
2813 symbol *tlbl = newiTempLabel (NULL);
2814 /* if the result is a bit */
2815 if (AOP_TYPE (result) == AOP_CRY)
2817 aopPut (AOP (result), "a", 0);
2821 emitcode ("jz", "%05d$", tlbl->key + 100);
2822 emitcode ("mov", "a,%s", one);
2823 emitcode ("", "%05d$:", tlbl->key + 100);
2828 /*-----------------------------------------------------------------*/
2829 /* genPlusBits - generates code for addition of two bits */
2830 /*-----------------------------------------------------------------*/
2832 genPlusBits (iCode * ic)
2834 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2836 symbol *lbl = newiTempLabel (NULL);
2837 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2838 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2839 emitcode ("cpl", "c");
2840 emitcode ("", "%05d$:", (lbl->key + 100));
2841 outBitC (IC_RESULT (ic));
2845 emitcode ("clr", "a");
2846 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2847 emitcode ("rlc", "a");
2848 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2849 emitcode ("addc", "a,#0x00");
2850 outAcc (IC_RESULT (ic));
2855 /* This is the original version of this code.
2857 * This is being kept around for reference,
2858 * because I am not entirely sure I got it right...
2861 adjustArithmeticResult (iCode * ic)
2863 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2864 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2865 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2866 aopPut (AOP (IC_RESULT (ic)),
2867 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2870 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2871 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2872 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2873 aopPut (AOP (IC_RESULT (ic)),
2874 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2877 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2878 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2879 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2880 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2881 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2884 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2885 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2889 /* This is the pure and virtuous version of this code.
2890 * I'm pretty certain it's right, but not enough to toss the old
2894 adjustArithmeticResult (iCode * ic)
2896 if (opIsGptr (IC_RESULT (ic)) &&
2897 opIsGptr (IC_LEFT (ic)) &&
2898 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2900 aopPut (AOP (IC_RESULT (ic)),
2901 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2905 if (opIsGptr (IC_RESULT (ic)) &&
2906 opIsGptr (IC_RIGHT (ic)) &&
2907 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2909 aopPut (AOP (IC_RESULT (ic)),
2910 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2914 if (opIsGptr (IC_RESULT (ic)) &&
2915 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2916 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2917 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2918 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2921 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2922 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2927 /*-----------------------------------------------------------------*/
2928 /* genPlus - generates code for addition */
2929 /*-----------------------------------------------------------------*/
2931 genPlus (iCode * ic)
2933 int size, offset = 0;
2935 /* special cases :- */
2937 aopOp (IC_LEFT (ic), ic, FALSE);
2938 aopOp (IC_RIGHT (ic), ic, FALSE);
2939 aopOp (IC_RESULT (ic), ic, TRUE);
2941 /* if literal, literal on the right or
2942 if left requires ACC or right is already
2944 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2945 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2946 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2948 operand *t = IC_RIGHT (ic);
2949 IC_RIGHT (ic) = IC_LEFT (ic);
2953 /* if both left & right are in bit
2955 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2956 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2962 /* if left in bit space & right literal */
2963 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2964 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2966 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2967 /* if result in bit space */
2968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2970 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2971 emitcode ("cpl", "c");
2972 outBitC (IC_RESULT (ic));
2976 size = getDataSize (IC_RESULT (ic));
2979 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2980 emitcode ("addc", "a,#00");
2981 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2987 /* if I can do an increment instead
2988 of add then GOOD for ME */
2989 if (genPlusIncr (ic) == TRUE)
2992 size = getDataSize (IC_RESULT (ic));
2996 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2998 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3000 emitcode ("add", "a,%s",
3001 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3003 emitcode ("addc", "a,%s",
3004 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3008 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3010 emitcode ("add", "a,%s",
3011 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3013 emitcode ("addc", "a,%s",
3014 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3016 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3019 adjustArithmeticResult (ic);
3022 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3023 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3024 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3027 /*-----------------------------------------------------------------*/
3028 /* genMinusDec :- does subtraction with deccrement if possible */
3029 /*-----------------------------------------------------------------*/
3031 genMinusDec (iCode * ic)
3033 unsigned int icount;
3034 unsigned int size = getDataSize (IC_RESULT (ic));
3036 /* will try to generate an increment */
3037 /* if the right side is not a literal
3039 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3042 /* if the literal value of the right hand side
3043 is greater than 4 then it is not worth it */
3044 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3047 /* if decrement 16 bits in register */
3048 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3056 /* If the next instruction is a goto and the goto target
3057 * is <= 10 instructions previous to this, we can generate
3058 * jumps straight to that target.
3060 if (ic->next && ic->next->op == GOTO
3061 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3062 && labelRange <= 10)
3064 emitcode (";", "tail decrement optimized");
3065 tlbl = IC_LABEL (ic->next);
3070 tlbl = newiTempLabel (NULL);
3074 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3075 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3076 IS_AOP_PREG (IC_RESULT (ic)))
3077 emitcode ("cjne", "%s,#0xff,%05d$"
3078 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3082 emitcode ("mov", "a,#0xff");
3083 emitcode ("cjne", "a,%s,%05d$"
3084 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3087 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3090 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3091 IS_AOP_PREG (IC_RESULT (ic)))
3092 emitcode ("cjne", "%s,#0xff,%05d$"
3093 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3097 emitcode ("cjne", "a,%s,%05d$"
3098 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3101 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3105 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3106 IS_AOP_PREG (IC_RESULT (ic)))
3107 emitcode ("cjne", "%s,#0xff,%05d$"
3108 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3112 emitcode ("cjne", "a,%s,%05d$"
3113 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3116 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3120 emitcode ("", "%05d$:", tlbl->key + 100);
3125 /* if the sizes are greater than 1 then we cannot */
3126 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3127 AOP_SIZE (IC_LEFT (ic)) > 1)
3130 /* we can if the aops of the left & result match or
3131 if they are in registers and the registers are the
3133 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3137 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3145 /*-----------------------------------------------------------------*/
3146 /* addSign - complete with sign */
3147 /*-----------------------------------------------------------------*/
3149 addSign (operand * result, int offset, int sign)
3151 int size = (getDataSize (result) - offset);
3156 emitcode ("rlc", "a");
3157 emitcode ("subb", "a,acc");
3159 aopPut (AOP (result), "a", offset++);
3163 aopPut (AOP (result), zero, offset++);
3167 /*-----------------------------------------------------------------*/
3168 /* genMinusBits - generates code for subtraction of two bits */
3169 /*-----------------------------------------------------------------*/
3171 genMinusBits (iCode * ic)
3173 symbol *lbl = newiTempLabel (NULL);
3174 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3176 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3177 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3178 emitcode ("cpl", "c");
3179 emitcode ("", "%05d$:", (lbl->key + 100));
3180 outBitC (IC_RESULT (ic));
3184 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3185 emitcode ("subb", "a,acc");
3186 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3187 emitcode ("inc", "a");
3188 emitcode ("", "%05d$:", (lbl->key + 100));
3189 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3190 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3194 /*-----------------------------------------------------------------*/
3195 /* genMinus - generates code for subtraction */
3196 /*-----------------------------------------------------------------*/
3198 genMinus (iCode * ic)
3200 int size, offset = 0;
3201 unsigned long lit = 0L;
3203 aopOp (IC_LEFT (ic), ic, FALSE);
3204 aopOp (IC_RIGHT (ic), ic, FALSE);
3205 aopOp (IC_RESULT (ic), ic, TRUE);
3207 /* special cases :- */
3208 /* if both left & right are in bit space */
3209 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3210 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3216 /* if I can do an decrement instead
3217 of subtract then GOOD for ME */
3218 if (genMinusDec (ic) == TRUE)
3221 size = getDataSize (IC_RESULT (ic));
3223 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3229 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3233 /* if literal, add a,#-lit, else normal subb */
3236 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3237 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3238 emitcode ("subb", "a,%s",
3239 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3242 /* first add without previous c */
3244 emitcode ("add", "a,#0x%02x",
3245 (unsigned int) (lit & 0x0FFL));
3247 emitcode ("addc", "a,#0x%02x",
3248 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3250 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3253 adjustArithmeticResult (ic);
3256 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3257 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3258 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3262 /*-----------------------------------------------------------------*/
3263 /* genMultbits :- multiplication of bits */
3264 /*-----------------------------------------------------------------*/
3266 genMultbits (operand * left,
3270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3271 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3276 /*-----------------------------------------------------------------*/
3277 /* genMultOneByte : 8*8=8/16 bit multiplication */
3278 /*-----------------------------------------------------------------*/
3280 genMultOneByte (operand * left,
3284 sym_link *opetype = operandType (result);
3286 int size=AOP_SIZE(result);
3288 //emitcode (";",__FUNCTION__);
3289 if (size<1 || size>2) {
3290 // this should never happen
3291 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3292 AOP_SIZE(result), __FILE__, lineno);
3296 /* (if two literals: the value is computed before) */
3297 /* if one literal, literal on the right */
3298 if (AOP_TYPE (left) == AOP_LIT)
3303 //emitcode (";", "swapped left and right");
3306 if (SPEC_USIGN(opetype)
3307 // ignore the sign of left and right, what else can we do?
3308 || (SPEC_USIGN(operandType(left)) &&
3309 SPEC_USIGN(operandType(right)))) {
3310 // just an unsigned 8*8=8/16 multiply
3311 //emitcode (";","unsigned");
3312 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3313 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3314 emitcode ("mul", "ab");
3315 aopPut (AOP (result), "a", 0);
3317 aopPut (AOP (result), "b", 1);
3322 // we have to do a signed multiply
3324 //emitcode (";", "signed");
3325 emitcode ("clr", "F0"); // reset sign flag
3326 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3327 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3329 lbl=newiTempLabel(NULL);
3330 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3331 // left side is negative, 8-bit two's complement, this fails for -128
3332 emitcode ("setb", "F0"); // set sign flag
3333 emitcode ("cpl", "a");
3334 emitcode ("inc", "a");
3336 emitcode ("", "%05d$:", lbl->key+100);
3337 emitcode ("xch", "a,b");
3340 if (AOP_TYPE(right)==AOP_LIT) {
3341 /* AND literal negative */
3342 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3343 // two's complement for literal<0
3344 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3345 emitcode ("cpl", "a");
3346 emitcode ("inc", "a");
3349 lbl=newiTempLabel(NULL);
3350 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3351 // right side is negative, 8-bit two's complement
3352 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3353 emitcode ("cpl", "a");
3354 emitcode ("inc", "a");
3355 emitcode ("", "%05d$:", lbl->key+100);
3357 emitcode ("mul", "ab");
3359 lbl=newiTempLabel(NULL);
3360 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3361 // only ONE op was negative, we have to do a 8/16-bit two's complement
3362 emitcode ("cpl", "a"); // lsb
3364 emitcode ("inc", "a");
3366 emitcode ("add", "a,#1");
3367 emitcode ("xch", "a,b");
3368 emitcode ("cpl", "a"); // msb
3369 emitcode ("addc", "a,#0");
3370 emitcode ("xch", "a,b");
3373 emitcode ("", "%05d$:", lbl->key+100);
3374 aopPut (AOP (result), "a", 0);
3376 aopPut (AOP (result), "b", 1);
3380 /*-----------------------------------------------------------------*/
3381 /* genMult - generates code for multiplication */
3382 /*-----------------------------------------------------------------*/
3384 genMult (iCode * ic)
3386 operand *left = IC_LEFT (ic);
3387 operand *right = IC_RIGHT (ic);
3388 operand *result = IC_RESULT (ic);
3390 /* assign the amsops */
3391 aopOp (left, ic, FALSE);
3392 aopOp (right, ic, FALSE);
3393 aopOp (result, ic, TRUE);
3395 /* special cases first */
3397 if (AOP_TYPE (left) == AOP_CRY &&
3398 AOP_TYPE (right) == AOP_CRY)
3400 genMultbits (left, right, result);
3404 /* if both are of size == 1 */
3405 if (AOP_SIZE (left) == 1 &&
3406 AOP_SIZE (right) == 1)
3408 genMultOneByte (left, right, result);
3412 /* should have been converted to function call */
3416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3418 freeAsmop (result, NULL, ic, TRUE);
3421 /*-----------------------------------------------------------------*/
3422 /* genDivbits :- division of bits */
3423 /*-----------------------------------------------------------------*/
3425 genDivbits (operand * left,
3432 /* the result must be bit */
3433 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3434 l = aopGet (AOP (left), 0, FALSE, FALSE);
3438 emitcode ("div", "ab");
3439 emitcode ("rrc", "a");
3440 aopPut (AOP (result), "c", 0);
3443 /*-----------------------------------------------------------------*/
3444 /* genDivOneByte : 8 bit division */
3445 /*-----------------------------------------------------------------*/
3447 genDivOneByte (operand * left,
3451 sym_link *opetype = operandType (result);
3456 size = AOP_SIZE (result) - 1;
3458 /* signed or unsigned */
3459 if (SPEC_USIGN (opetype))
3461 /* unsigned is easy */
3462 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3463 l = aopGet (AOP (left), 0, FALSE, FALSE);
3465 emitcode ("div", "ab");
3466 aopPut (AOP (result), "a", 0);
3468 aopPut (AOP (result), zero, offset++);
3472 /* signed is a little bit more difficult */
3474 /* save the signs of the operands */
3475 l = aopGet (AOP (left), 0, FALSE, FALSE);
3477 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3478 emitcode ("push", "acc"); /* save it on the stack */
3480 /* now sign adjust for both left & right */
3481 l = aopGet (AOP (right), 0, FALSE, FALSE);
3483 lbl = newiTempLabel (NULL);
3484 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3485 emitcode ("cpl", "a");
3486 emitcode ("inc", "a");
3487 emitcode ("", "%05d$:", (lbl->key + 100));
3488 emitcode ("mov", "b,a");
3490 /* sign adjust left side */
3491 l = aopGet (AOP (left), 0, FALSE, FALSE);
3494 lbl = newiTempLabel (NULL);
3495 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3496 emitcode ("cpl", "a");
3497 emitcode ("inc", "a");
3498 emitcode ("", "%05d$:", (lbl->key + 100));
3500 /* now the division */
3501 emitcode ("div", "ab");
3502 /* we are interested in the lower order
3504 emitcode ("mov", "b,a");
3505 lbl = newiTempLabel (NULL);
3506 emitcode ("pop", "acc");
3507 /* if there was an over flow we don't
3508 adjust the sign of the result */
3509 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3510 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3512 emitcode ("clr", "a");
3513 emitcode ("subb", "a,b");
3514 emitcode ("mov", "b,a");
3515 emitcode ("", "%05d$:", (lbl->key + 100));
3517 /* now we are done */
3518 aopPut (AOP (result), "b", 0);
3521 emitcode ("mov", "c,b.7");
3522 emitcode ("subb", "a,acc");
3525 aopPut (AOP (result), "a", offset++);
3529 /*-----------------------------------------------------------------*/
3530 /* genDiv - generates code for division */
3531 /*-----------------------------------------------------------------*/
3535 operand *left = IC_LEFT (ic);
3536 operand *right = IC_RIGHT (ic);
3537 operand *result = IC_RESULT (ic);
3539 /* assign the amsops */
3540 aopOp (left, ic, FALSE);
3541 aopOp (right, ic, FALSE);
3542 aopOp (result, ic, TRUE);
3544 /* special cases first */
3546 if (AOP_TYPE (left) == AOP_CRY &&
3547 AOP_TYPE (right) == AOP_CRY)
3549 genDivbits (left, right, result);
3553 /* if both are of size == 1 */
3554 if (AOP_SIZE (left) == 1 &&
3555 AOP_SIZE (right) == 1)
3557 genDivOneByte (left, right, result);
3561 /* should have been converted to function call */
3564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3566 freeAsmop (result, NULL, ic, TRUE);
3569 /*-----------------------------------------------------------------*/
3570 /* genModbits :- modulus of bits */
3571 /*-----------------------------------------------------------------*/
3573 genModbits (operand * left,
3580 /* the result must be bit */
3581 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3582 l = aopGet (AOP (left), 0, FALSE, FALSE);
3586 emitcode ("div", "ab");
3587 emitcode ("mov", "a,b");
3588 emitcode ("rrc", "a");
3589 aopPut (AOP (result), "c", 0);
3592 /*-----------------------------------------------------------------*/
3593 /* genModOneByte : 8 bit modulus */
3594 /*-----------------------------------------------------------------*/
3596 genModOneByte (operand * left,
3600 sym_link *opetype = operandType (result);
3604 /* signed or unsigned */
3605 if (SPEC_USIGN (opetype))
3607 /* unsigned is easy */
3608 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3609 l = aopGet (AOP (left), 0, FALSE, FALSE);
3611 emitcode ("div", "ab");
3612 aopPut (AOP (result), "b", 0);
3616 /* signed is a little bit more difficult */
3618 /* save the signs of the operands */
3619 l = aopGet (AOP (left), 0, FALSE, FALSE);
3622 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3623 emitcode ("push", "acc"); /* save it on the stack */
3625 /* now sign adjust for both left & right */
3626 l = aopGet (AOP (right), 0, FALSE, FALSE);
3629 lbl = newiTempLabel (NULL);
3630 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3631 emitcode ("cpl", "a");
3632 emitcode ("inc", "a");
3633 emitcode ("", "%05d$:", (lbl->key + 100));
3634 emitcode ("mov", "b,a");
3636 /* sign adjust left side */
3637 l = aopGet (AOP (left), 0, FALSE, FALSE);
3640 lbl = newiTempLabel (NULL);
3641 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3642 emitcode ("cpl", "a");
3643 emitcode ("inc", "a");
3644 emitcode ("", "%05d$:", (lbl->key + 100));
3646 /* now the multiplication */
3647 emitcode ("div", "ab");
3648 /* we are interested in the lower order
3650 lbl = newiTempLabel (NULL);
3651 emitcode ("pop", "acc");
3652 /* if there was an over flow we don't
3653 adjust the sign of the result */
3654 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3655 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3657 emitcode ("clr", "a");
3658 emitcode ("subb", "a,b");
3659 emitcode ("mov", "b,a");
3660 emitcode ("", "%05d$:", (lbl->key + 100));
3662 /* now we are done */
3663 aopPut (AOP (result), "b", 0);
3667 /*-----------------------------------------------------------------*/
3668 /* genMod - generates code for division */
3669 /*-----------------------------------------------------------------*/
3673 operand *left = IC_LEFT (ic);
3674 operand *right = IC_RIGHT (ic);
3675 operand *result = IC_RESULT (ic);
3677 /* assign the amsops */
3678 aopOp (left, ic, FALSE);
3679 aopOp (right, ic, FALSE);
3680 aopOp (result, ic, TRUE);
3682 /* special cases first */
3684 if (AOP_TYPE (left) == AOP_CRY &&
3685 AOP_TYPE (right) == AOP_CRY)
3687 genModbits (left, right, result);
3691 /* if both are of size == 1 */
3692 if (AOP_SIZE (left) == 1 &&
3693 AOP_SIZE (right) == 1)
3695 genModOneByte (left, right, result);
3699 /* should have been converted to function call */
3703 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3705 freeAsmop (result, NULL, ic, TRUE);
3708 /*-----------------------------------------------------------------*/
3709 /* genIfxJump :- will create a jump depending on the ifx */
3710 /*-----------------------------------------------------------------*/
3712 genIfxJump (iCode * ic, char *jval)
3715 symbol *tlbl = newiTempLabel (NULL);
3718 /* if true label then we jump if condition
3722 jlbl = IC_TRUE (ic);
3723 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3724 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3728 /* false label is present */
3729 jlbl = IC_FALSE (ic);
3730 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3731 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3733 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3734 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3736 emitcode (inst, "%05d$", tlbl->key + 100);
3737 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3738 emitcode ("", "%05d$:", tlbl->key + 100);
3740 /* mark the icode as generated */
3744 /*-----------------------------------------------------------------*/
3745 /* genCmp :- greater or less than comparison */
3746 /*-----------------------------------------------------------------*/
3748 genCmp (operand * left, operand * right,
3749 operand * result, iCode * ifx, int sign, iCode *ic)
3751 int size, offset = 0;
3752 unsigned long lit = 0L;
3754 /* if left & right are bit variables */
3755 if (AOP_TYPE (left) == AOP_CRY &&
3756 AOP_TYPE (right) == AOP_CRY)
3758 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3759 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3763 /* subtract right from left if at the
3764 end the carry flag is set then we know that
3765 left is greater than right */
3766 size = max (AOP_SIZE (left), AOP_SIZE (right));
3768 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3769 if ((size == 1) && !sign &&
3770 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3772 symbol *lbl = newiTempLabel (NULL);
3773 emitcode ("cjne", "%s,%s,%05d$",
3774 aopGet (AOP (left), offset, FALSE, FALSE),
3775 aopGet (AOP (right), offset, FALSE, FALSE),
3777 emitcode ("", "%05d$:", lbl->key + 100);
3781 if (AOP_TYPE (right) == AOP_LIT)
3783 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3784 /* optimize if(x < 0) or if(x >= 0) */
3793 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3794 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3796 genIfxJump (ifx, "acc.7");
3800 emitcode ("rlc", "a");
3808 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3809 if (sign && size == 0)
3811 emitcode ("xrl", "a,#0x80");
3812 if (AOP_TYPE (right) == AOP_LIT)
3814 unsigned long lit = (unsigned long)
3815 floatFromVal (AOP (right)->aopu.aop_lit);
3816 emitcode ("subb", "a,#0x%02x",
3817 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3821 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3822 emitcode ("xrl", "b,#0x80");
3823 emitcode ("subb", "a,b");
3827 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3833 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3834 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3835 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3841 /* if the result is used in the next
3842 ifx conditional branch then generate
3843 code a little differently */
3845 genIfxJump (ifx, "c");
3848 /* leave the result in acc */
3852 /*-----------------------------------------------------------------*/
3853 /* genCmpGt :- greater than comparison */
3854 /*-----------------------------------------------------------------*/
3856 genCmpGt (iCode * ic, iCode * ifx)
3858 operand *left, *right, *result;
3859 sym_link *letype, *retype;
3862 left = IC_LEFT (ic);
3863 right = IC_RIGHT (ic);
3864 result = IC_RESULT (ic);
3866 letype = getSpec (operandType (left));
3867 retype = getSpec (operandType (right));
3868 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3869 /* assign the amsops */
3870 aopOp (left, ic, FALSE);
3871 aopOp (right, ic, FALSE);
3872 aopOp (result, ic, TRUE);
3874 genCmp (right, left, result, ifx, sign,ic);
3876 freeAsmop (result, NULL, ic, TRUE);
3879 /*-----------------------------------------------------------------*/
3880 /* genCmpLt - less than comparisons */
3881 /*-----------------------------------------------------------------*/
3883 genCmpLt (iCode * ic, iCode * ifx)
3885 operand *left, *right, *result;
3886 sym_link *letype, *retype;
3889 left = IC_LEFT (ic);
3890 right = IC_RIGHT (ic);
3891 result = IC_RESULT (ic);
3893 letype = getSpec (operandType (left));
3894 retype = getSpec (operandType (right));
3895 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3897 /* assign the amsops */
3898 aopOp (left, ic, FALSE);
3899 aopOp (right, ic, FALSE);
3900 aopOp (result, ic, TRUE);
3902 genCmp (left, right, result, ifx, sign,ic);
3904 freeAsmop (result, NULL, ic, TRUE);
3907 /*-----------------------------------------------------------------*/
3908 /* gencjneshort - compare and jump if not equal */
3909 /*-----------------------------------------------------------------*/
3911 gencjneshort (operand * left, operand * right, symbol * lbl)
3913 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3915 unsigned long lit = 0L;
3917 /* if the left side is a literal or
3918 if the right is in a pointer register and left
3920 if ((AOP_TYPE (left) == AOP_LIT) ||
3921 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3927 if (AOP_TYPE (right) == AOP_LIT)
3928 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3930 /* if the right side is a literal then anything goes */
3931 if (AOP_TYPE (right) == AOP_LIT &&
3932 AOP_TYPE (left) != AOP_DIR)
3936 emitcode ("cjne", "%s,%s,%05d$",
3937 aopGet (AOP (left), offset, FALSE, FALSE),
3938 aopGet (AOP (right), offset, FALSE, FALSE),
3944 /* if the right side is in a register or in direct space or
3945 if the left is a pointer register & right is not */
3946 else if (AOP_TYPE (right) == AOP_REG ||
3947 AOP_TYPE (right) == AOP_DIR ||
3948 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3949 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3953 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3954 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3955 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3956 emitcode ("jnz", "%05d$", lbl->key + 100);
3958 emitcode ("cjne", "a,%s,%05d$",
3959 aopGet (AOP (right), offset, FALSE, TRUE),
3966 /* right is a pointer reg need both a & b */
3969 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3970 if (strcmp (l, "b"))
3971 emitcode ("mov", "b,%s", l);
3972 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3973 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3979 /*-----------------------------------------------------------------*/
3980 /* gencjne - compare and jump if not equal */
3981 /*-----------------------------------------------------------------*/
3983 gencjne (operand * left, operand * right, symbol * lbl)
3985 symbol *tlbl = newiTempLabel (NULL);
3987 gencjneshort (left, right, lbl);
3989 emitcode ("mov", "a,%s", one);
3990 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3991 emitcode ("", "%05d$:", lbl->key + 100);
3992 emitcode ("clr", "a");
3993 emitcode ("", "%05d$:", tlbl->key + 100);
3996 /*-----------------------------------------------------------------*/
3997 /* genCmpEq - generates code for equal to */
3998 /*-----------------------------------------------------------------*/
4000 genCmpEq (iCode * ic, iCode * ifx)
4002 operand *left, *right, *result;
4004 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4005 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4006 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4008 /* if literal, literal on the right or
4009 if the right is in a pointer register and left
4011 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4012 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4014 operand *t = IC_RIGHT (ic);
4015 IC_RIGHT (ic) = IC_LEFT (ic);
4019 if (ifx && !AOP_SIZE (result))
4022 /* if they are both bit variables */
4023 if (AOP_TYPE (left) == AOP_CRY &&
4024 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4026 if (AOP_TYPE (right) == AOP_LIT)
4028 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4031 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4032 emitcode ("cpl", "c");
4036 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4040 emitcode ("clr", "c");
4042 /* AOP_TYPE(right) == AOP_CRY */
4046 symbol *lbl = newiTempLabel (NULL);
4047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4048 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4049 emitcode ("cpl", "c");
4050 emitcode ("", "%05d$:", (lbl->key + 100));
4052 /* if true label then we jump if condition
4054 tlbl = newiTempLabel (NULL);
4057 emitcode ("jnc", "%05d$", tlbl->key + 100);
4058 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4062 emitcode ("jc", "%05d$", tlbl->key + 100);
4063 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4065 emitcode ("", "%05d$:", tlbl->key + 100);
4069 tlbl = newiTempLabel (NULL);
4070 gencjneshort (left, right, tlbl);
4073 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4074 emitcode ("", "%05d$:", tlbl->key + 100);
4078 symbol *lbl = newiTempLabel (NULL);
4079 emitcode ("sjmp", "%05d$", lbl->key + 100);
4080 emitcode ("", "%05d$:", tlbl->key + 100);
4081 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4082 emitcode ("", "%05d$:", lbl->key + 100);
4085 /* mark the icode as generated */
4090 /* if they are both bit variables */
4091 if (AOP_TYPE (left) == AOP_CRY &&
4092 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4094 if (AOP_TYPE (right) == AOP_LIT)
4096 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4099 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4100 emitcode ("cpl", "c");
4104 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4108 emitcode ("clr", "c");
4110 /* AOP_TYPE(right) == AOP_CRY */
4114 symbol *lbl = newiTempLabel (NULL);
4115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4116 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4117 emitcode ("cpl", "c");
4118 emitcode ("", "%05d$:", (lbl->key + 100));
4121 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4128 genIfxJump (ifx, "c");
4131 /* if the result is used in an arithmetic operation
4132 then put the result in place */
4137 gencjne (left, right, newiTempLabel (NULL));
4138 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4140 aopPut (AOP (result), "a", 0);
4145 genIfxJump (ifx, "a");
4148 /* if the result is used in an arithmetic operation
4149 then put the result in place */
4150 if (AOP_TYPE (result) != AOP_CRY)
4152 /* leave the result in acc */
4156 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4158 freeAsmop (result, NULL, ic, TRUE);
4161 /*-----------------------------------------------------------------*/
4162 /* ifxForOp - returns the icode containing the ifx for operand */
4163 /*-----------------------------------------------------------------*/
4165 ifxForOp (operand * op, iCode * ic)
4167 /* if true symbol then needs to be assigned */
4168 if (IS_TRUE_SYMOP (op))
4171 /* if this has register type condition and
4172 the next instruction is ifx with the same operand
4173 and live to of the operand is upto the ifx only then */
4175 ic->next->op == IFX &&
4176 IC_COND (ic->next)->key == op->key &&
4177 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4183 /*-----------------------------------------------------------------*/
4184 /* hasInc - operand is incremented before any other use */
4185 /*-----------------------------------------------------------------*/
4187 hasInc (operand *op, iCode *ic)
4189 sym_link *type = operandType(op);
4190 sym_link *retype = getSpec (type);
4191 iCode *lic = ic->next;
4194 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4195 isize = getSize(type->next);
4197 /* if operand of the form op = op + <sizeof *op> */
4198 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4199 isOperandEqual(IC_RESULT(lic),op) &&
4200 isOperandLiteral(IC_RIGHT(lic)) &&
4201 operandLitValue(IC_RIGHT(lic)) == isize) {
4204 /* if the operand used or deffed */
4205 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4213 /*-----------------------------------------------------------------*/
4214 /* genAndOp - for && operation */
4215 /*-----------------------------------------------------------------*/
4217 genAndOp (iCode * ic)
4219 operand *left, *right, *result;
4222 /* note here that && operations that are in an
4223 if statement are taken away by backPatchLabels
4224 only those used in arthmetic operations remain */
4225 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4226 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4227 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4229 /* if both are bit variables */
4230 if (AOP_TYPE (left) == AOP_CRY &&
4231 AOP_TYPE (right) == AOP_CRY)
4233 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4234 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4239 tlbl = newiTempLabel (NULL);
4241 emitcode ("jz", "%05d$", tlbl->key + 100);
4243 emitcode ("", "%05d$:", tlbl->key + 100);
4247 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4248 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4249 freeAsmop (result, NULL, ic, TRUE);
4253 /*-----------------------------------------------------------------*/
4254 /* genOrOp - for || operation */
4255 /*-----------------------------------------------------------------*/
4257 genOrOp (iCode * ic)
4259 operand *left, *right, *result;
4262 /* note here that || operations that are in an
4263 if statement are taken away by backPatchLabels
4264 only those used in arthmetic operations remain */
4265 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4266 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4267 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4269 /* if both are bit variables */
4270 if (AOP_TYPE (left) == AOP_CRY &&
4271 AOP_TYPE (right) == AOP_CRY)
4273 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4274 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4279 tlbl = newiTempLabel (NULL);
4281 emitcode ("jnz", "%05d$", tlbl->key + 100);
4283 emitcode ("", "%05d$:", tlbl->key + 100);
4287 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4289 freeAsmop (result, NULL, ic, TRUE);
4292 /*-----------------------------------------------------------------*/
4293 /* isLiteralBit - test if lit == 2^n */
4294 /*-----------------------------------------------------------------*/
4296 isLiteralBit (unsigned long lit)
4298 unsigned long pw[32] =
4299 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4300 0x100L, 0x200L, 0x400L, 0x800L,
4301 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4302 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4303 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4304 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4305 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4308 for (idx = 0; idx < 32; idx++)
4314 /*-----------------------------------------------------------------*/
4315 /* continueIfTrue - */
4316 /*-----------------------------------------------------------------*/
4318 continueIfTrue (iCode * ic)
4321 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4325 /*-----------------------------------------------------------------*/
4327 /*-----------------------------------------------------------------*/
4329 jumpIfTrue (iCode * ic)
4332 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4336 /*-----------------------------------------------------------------*/
4337 /* jmpTrueOrFalse - */
4338 /*-----------------------------------------------------------------*/
4340 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4342 // ugly but optimized by peephole
4345 symbol *nlbl = newiTempLabel (NULL);
4346 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4347 emitcode ("", "%05d$:", tlbl->key + 100);
4348 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4349 emitcode ("", "%05d$:", nlbl->key + 100);
4353 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4354 emitcode ("", "%05d$:", tlbl->key + 100);
4359 /*-----------------------------------------------------------------*/
4360 /* genAnd - code for and */
4361 /*-----------------------------------------------------------------*/
4363 genAnd (iCode * ic, iCode * ifx)
4365 operand *left, *right, *result;
4366 int size, offset = 0;
4367 unsigned long lit = 0L;
4371 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4372 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4373 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4376 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4378 AOP_TYPE (left), AOP_TYPE (right));
4379 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4381 AOP_SIZE (left), AOP_SIZE (right));
4384 /* if left is a literal & right is not then exchange them */
4385 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4386 AOP_NEEDSACC (left))
4388 operand *tmp = right;
4393 /* if result = right then exchange them */
4394 if (sameRegs (AOP (result), AOP (right)))
4396 operand *tmp = right;
4401 /* if right is bit then exchange them */
4402 if (AOP_TYPE (right) == AOP_CRY &&
4403 AOP_TYPE (left) != AOP_CRY)
4405 operand *tmp = right;
4409 if (AOP_TYPE (right) == AOP_LIT)
4410 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4412 size = AOP_SIZE (result);
4415 // result = bit & yy;
4416 if (AOP_TYPE (left) == AOP_CRY)
4418 // c = bit & literal;
4419 if (AOP_TYPE (right) == AOP_LIT)
4423 if (size && sameRegs (AOP (result), AOP (left)))
4426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4431 if (size && (AOP_TYPE (result) == AOP_CRY))
4433 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4436 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4441 emitcode ("clr", "c");
4446 if (AOP_TYPE (right) == AOP_CRY)
4449 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4450 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4455 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4457 emitcode ("rrc", "a");
4458 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4466 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4467 genIfxJump (ifx, "c");
4471 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4472 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4473 if ((AOP_TYPE (right) == AOP_LIT) &&
4474 (AOP_TYPE (result) == AOP_CRY) &&
4475 (AOP_TYPE (left) != AOP_CRY))
4477 int posbit = isLiteralBit (lit);
4482 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4485 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4491 sprintf (buffer, "acc.%d", posbit & 0x07);
4492 genIfxJump (ifx, buffer);
4499 symbol *tlbl = newiTempLabel (NULL);
4500 int sizel = AOP_SIZE (left);
4502 emitcode ("setb", "c");
4505 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4507 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4509 if ((posbit = isLiteralBit (bytelit)) != 0)
4510 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4513 if (bytelit != 0x0FFL)
4514 emitcode ("anl", "a,%s",
4515 aopGet (AOP (right), offset, FALSE, TRUE));
4516 emitcode ("jnz", "%05d$", tlbl->key + 100);
4521 // bit = left & literal
4524 emitcode ("clr", "c");
4525 emitcode ("", "%05d$:", tlbl->key + 100);
4527 // if(left & literal)
4531 jmpTrueOrFalse (ifx, tlbl);
4539 /* if left is same as result */
4540 if (sameRegs (AOP (result), AOP (left)))
4542 for (; size--; offset++)
4544 if (AOP_TYPE (right) == AOP_LIT)
4546 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4548 else if (bytelit == 0)
4549 aopPut (AOP (result), zero, offset);
4550 else if (IS_AOP_PREG (result))
4552 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4553 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4554 aopPut (AOP (result), "a", offset);
4557 emitcode ("anl", "%s,%s",
4558 aopGet (AOP (left), offset, FALSE, TRUE),
4559 aopGet (AOP (right), offset, FALSE, FALSE));
4563 if (AOP_TYPE (left) == AOP_ACC)
4564 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4567 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4568 if (IS_AOP_PREG (result))
4570 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4571 aopPut (AOP (result), "a", offset);
4575 emitcode ("anl", "%s,a",
4576 aopGet (AOP (left), offset, FALSE, TRUE));
4583 // left & result in different registers
4584 if (AOP_TYPE (result) == AOP_CRY)
4587 // if(size), result in bit
4588 // if(!size && ifx), conditional oper: if(left & right)
4589 symbol *tlbl = newiTempLabel (NULL);
4590 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4592 emitcode ("setb", "c");
4595 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4596 emitcode ("anl", "a,%s",
4597 aopGet (AOP (left), offset, FALSE, FALSE));
4598 emitcode ("jnz", "%05d$", tlbl->key + 100);
4604 emitcode ("", "%05d$:", tlbl->key + 100);
4608 jmpTrueOrFalse (ifx, tlbl);
4612 for (; (size--); offset++)
4615 // result = left & right
4616 if (AOP_TYPE (right) == AOP_LIT)
4618 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4620 aopPut (AOP (result),
4621 aopGet (AOP (left), offset, FALSE, FALSE),
4625 else if (bytelit == 0)
4627 aopPut (AOP (result), zero, offset);
4631 // faster than result <- left, anl result,right
4632 // and better if result is SFR
4633 if (AOP_TYPE (left) == AOP_ACC)
4634 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4637 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4638 emitcode ("anl", "a,%s",
4639 aopGet (AOP (left), offset, FALSE, FALSE));
4641 aopPut (AOP (result), "a", offset);
4647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4649 freeAsmop (result, NULL, ic, TRUE);
4652 /*-----------------------------------------------------------------*/
4653 /* genOr - code for or */
4654 /*-----------------------------------------------------------------*/
4656 genOr (iCode * ic, iCode * ifx)
4658 operand *left, *right, *result;
4659 int size, offset = 0;
4660 unsigned long lit = 0L;
4662 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4663 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4664 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4667 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4669 AOP_TYPE (left), AOP_TYPE (right));
4670 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4672 AOP_SIZE (left), AOP_SIZE (right));
4675 /* if left is a literal & right is not then exchange them */
4676 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4677 AOP_NEEDSACC (left))
4679 operand *tmp = right;
4684 /* if result = right then exchange them */
4685 if (sameRegs (AOP (result), AOP (right)))
4687 operand *tmp = right;
4692 /* if right is bit then exchange them */
4693 if (AOP_TYPE (right) == AOP_CRY &&
4694 AOP_TYPE (left) != AOP_CRY)
4696 operand *tmp = right;
4700 if (AOP_TYPE (right) == AOP_LIT)
4701 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4703 size = AOP_SIZE (result);
4707 if (AOP_TYPE (left) == AOP_CRY)
4709 if (AOP_TYPE (right) == AOP_LIT)
4711 // c = bit & literal;
4714 // lit != 0 => result = 1
4715 if (AOP_TYPE (result) == AOP_CRY)
4718 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4720 continueIfTrue (ifx);
4723 emitcode ("setb", "c");
4727 // lit == 0 => result = left
4728 if (size && sameRegs (AOP (result), AOP (left)))
4730 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4735 if (AOP_TYPE (right) == AOP_CRY)
4738 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4739 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4744 symbol *tlbl = newiTempLabel (NULL);
4745 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4746 emitcode ("setb", "c");
4747 emitcode ("jb", "%s,%05d$",
4748 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4750 emitcode ("jnz", "%05d$", tlbl->key + 100);
4751 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4753 jmpTrueOrFalse (ifx, tlbl);
4759 emitcode ("", "%05d$:", tlbl->key + 100);
4768 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4769 genIfxJump (ifx, "c");
4773 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4774 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4775 if ((AOP_TYPE (right) == AOP_LIT) &&
4776 (AOP_TYPE (result) == AOP_CRY) &&
4777 (AOP_TYPE (left) != AOP_CRY))
4783 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4785 continueIfTrue (ifx);
4790 // lit = 0, result = boolean(left)
4792 emitcode ("setb", "c");
4796 symbol *tlbl = newiTempLabel (NULL);
4797 emitcode ("jnz", "%05d$", tlbl->key + 100);
4799 emitcode ("", "%05d$:", tlbl->key + 100);
4803 genIfxJump (ifx, "a");
4811 /* if left is same as result */
4812 if (sameRegs (AOP (result), AOP (left)))
4814 for (; size--; offset++)
4816 if (AOP_TYPE (right) == AOP_LIT)
4818 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4820 else if (IS_AOP_PREG (left))
4822 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4823 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4824 aopPut (AOP (result), "a", offset);
4827 emitcode ("orl", "%s,%s",
4828 aopGet (AOP (left), offset, FALSE, TRUE),
4829 aopGet (AOP (right), offset, FALSE, FALSE));
4833 if (AOP_TYPE (left) == AOP_ACC)
4834 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4837 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4838 if (IS_AOP_PREG (left))
4840 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4841 aopPut (AOP (result), "a", offset);
4844 emitcode ("orl", "%s,a",
4845 aopGet (AOP (left), offset, FALSE, TRUE));
4852 // left & result in different registers
4853 if (AOP_TYPE (result) == AOP_CRY)
4856 // if(size), result in bit
4857 // if(!size && ifx), conditional oper: if(left | right)
4858 symbol *tlbl = newiTempLabel (NULL);
4859 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4861 emitcode ("setb", "c");
4864 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4865 emitcode ("orl", "a,%s",
4866 aopGet (AOP (left), offset, FALSE, FALSE));
4867 emitcode ("jnz", "%05d$", tlbl->key + 100);
4873 emitcode ("", "%05d$:", tlbl->key + 100);
4877 jmpTrueOrFalse (ifx, tlbl);
4880 for (; (size--); offset++)
4883 // result = left & right
4884 if (AOP_TYPE (right) == AOP_LIT)
4886 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4888 aopPut (AOP (result),
4889 aopGet (AOP (left), offset, FALSE, FALSE),
4894 // faster than result <- left, anl result,right
4895 // and better if result is SFR
4896 if (AOP_TYPE (left) == AOP_ACC)
4897 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4900 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4901 emitcode ("orl", "a,%s",
4902 aopGet (AOP (left), offset, FALSE, FALSE));
4904 aopPut (AOP (result), "a", offset);
4909 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4910 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4911 freeAsmop (result, NULL, ic, TRUE);
4914 /*-----------------------------------------------------------------*/
4915 /* genXor - code for xclusive or */
4916 /*-----------------------------------------------------------------*/
4918 genXor (iCode * ic, iCode * ifx)
4920 operand *left, *right, *result;
4921 int size, offset = 0;
4922 unsigned long lit = 0L;
4924 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4925 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4926 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4929 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4931 AOP_TYPE (left), AOP_TYPE (right));
4932 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4934 AOP_SIZE (left), AOP_SIZE (right));
4937 /* if left is a literal & right is not ||
4938 if left needs acc & right does not */
4939 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4940 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4942 operand *tmp = right;
4947 /* if result = right then exchange them */
4948 if (sameRegs (AOP (result), AOP (right)))
4950 operand *tmp = right;
4955 /* if right is bit then exchange them */
4956 if (AOP_TYPE (right) == AOP_CRY &&
4957 AOP_TYPE (left) != AOP_CRY)
4959 operand *tmp = right;
4963 if (AOP_TYPE (right) == AOP_LIT)
4964 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4966 size = AOP_SIZE (result);
4970 if (AOP_TYPE (left) == AOP_CRY)
4972 if (AOP_TYPE (right) == AOP_LIT)
4974 // c = bit & literal;
4977 // lit>>1 != 0 => result = 1
4978 if (AOP_TYPE (result) == AOP_CRY)
4981 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4983 continueIfTrue (ifx);
4986 emitcode ("setb", "c");
4993 // lit == 0, result = left
4994 if (size && sameRegs (AOP (result), AOP (left)))
4996 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5000 // lit == 1, result = not(left)
5001 if (size && sameRegs (AOP (result), AOP (left)))
5003 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5008 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5009 emitcode ("cpl", "c");
5018 symbol *tlbl = newiTempLabel (NULL);
5019 if (AOP_TYPE (right) == AOP_CRY)
5022 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5026 int sizer = AOP_SIZE (right);
5028 // if val>>1 != 0, result = 1
5029 emitcode ("setb", "c");
5032 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5034 // test the msb of the lsb
5035 emitcode ("anl", "a,#0xfe");
5036 emitcode ("jnz", "%05d$", tlbl->key + 100);
5040 emitcode ("rrc", "a");
5042 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5043 emitcode ("cpl", "c");
5044 emitcode ("", "%05d$:", (tlbl->key + 100));
5051 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5052 genIfxJump (ifx, "c");
5056 if (sameRegs (AOP (result), AOP (left)))
5058 /* if left is same as result */
5059 for (; size--; offset++)
5061 if (AOP_TYPE (right) == AOP_LIT)
5063 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5065 else if (IS_AOP_PREG (left))
5067 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5068 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5069 aopPut (AOP (result), "a", offset);
5072 emitcode ("xrl", "%s,%s",
5073 aopGet (AOP (left), offset, FALSE, TRUE),
5074 aopGet (AOP (right), offset, FALSE, FALSE));
5078 if (AOP_TYPE (left) == AOP_ACC)
5079 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5082 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5083 if (IS_AOP_PREG (left))
5085 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5086 aopPut (AOP (result), "a", offset);
5089 emitcode ("xrl", "%s,a",
5090 aopGet (AOP (left), offset, FALSE, TRUE));
5097 // left & result in different registers
5098 if (AOP_TYPE (result) == AOP_CRY)
5101 // if(size), result in bit
5102 // if(!size && ifx), conditional oper: if(left ^ right)
5103 symbol *tlbl = newiTempLabel (NULL);
5104 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5106 emitcode ("setb", "c");
5109 if ((AOP_TYPE (right) == AOP_LIT) &&
5110 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5112 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5116 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5117 emitcode ("xrl", "a,%s",
5118 aopGet (AOP (left), offset, FALSE, FALSE));
5120 emitcode ("jnz", "%05d$", tlbl->key + 100);
5126 emitcode ("", "%05d$:", tlbl->key + 100);
5130 jmpTrueOrFalse (ifx, tlbl);
5133 for (; (size--); offset++)
5136 // result = left & right
5137 if (AOP_TYPE (right) == AOP_LIT)
5139 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5141 aopPut (AOP (result),
5142 aopGet (AOP (left), offset, FALSE, FALSE),
5147 // faster than result <- left, anl result,right
5148 // and better if result is SFR
5149 if (AOP_TYPE (left) == AOP_ACC)
5150 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5154 emitcode ("xrl", "a,%s",
5155 aopGet (AOP (left), offset, FALSE, TRUE));
5157 aopPut (AOP (result), "a", offset);
5162 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5163 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5164 freeAsmop (result, NULL, ic, TRUE);
5167 /*-----------------------------------------------------------------*/
5168 /* genInline - write the inline code out */
5169 /*-----------------------------------------------------------------*/
5171 genInline (iCode * ic)
5173 char *buffer, *bp, *bp1;
5175 _G.inLine += (!options.asmpeep);
5177 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5178 strcpy (buffer, IC_INLINE (ic));
5180 /* emit each line as a code */
5205 /* emitcode("",buffer); */
5206 _G.inLine -= (!options.asmpeep);
5209 /*-----------------------------------------------------------------*/
5210 /* genRRC - rotate right with carry */
5211 /*-----------------------------------------------------------------*/
5215 operand *left, *result;
5216 int size, offset = 0;
5219 /* rotate right with carry */
5220 left = IC_LEFT (ic);
5221 result = IC_RESULT (ic);
5222 aopOp (left, ic, FALSE);
5223 aopOp (result, ic, FALSE);
5225 /* move it to the result */
5226 size = AOP_SIZE (result);
5231 l = aopGet (AOP (left), offset, FALSE, FALSE);
5233 emitcode ("rrc", "a");
5234 if (AOP_SIZE (result) > 1)
5235 aopPut (AOP (result), "a", offset--);
5237 /* now we need to put the carry into the
5238 highest order byte of the result */
5239 if (AOP_SIZE (result) > 1)
5241 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5244 emitcode ("mov", "acc.7,c");
5245 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5246 freeAsmop (left, NULL, ic, TRUE);
5247 freeAsmop (result, NULL, ic, TRUE);
5250 /*-----------------------------------------------------------------*/
5251 /* genRLC - generate code for rotate left with carry */
5252 /*-----------------------------------------------------------------*/
5256 operand *left, *result;
5257 int size, offset = 0;
5260 /* rotate right with carry */
5261 left = IC_LEFT (ic);
5262 result = IC_RESULT (ic);
5263 aopOp (left, ic, FALSE);
5264 aopOp (result, ic, FALSE);
5266 /* move it to the result */
5267 size = AOP_SIZE (result);
5271 l = aopGet (AOP (left), offset, FALSE, FALSE);
5273 emitcode ("add", "a,acc");
5274 if (AOP_SIZE (result) > 1)
5275 aopPut (AOP (result), "a", offset++);
5278 l = aopGet (AOP (left), offset, FALSE, FALSE);
5280 emitcode ("rlc", "a");
5281 if (AOP_SIZE (result) > 1)
5282 aopPut (AOP (result), "a", offset++);
5285 /* now we need to put the carry into the
5286 highest order byte of the result */
5287 if (AOP_SIZE (result) > 1)
5289 l = aopGet (AOP (result), 0, FALSE, FALSE);
5292 emitcode ("mov", "acc.0,c");
5293 aopPut (AOP (result), "a", 0);
5294 freeAsmop (left, NULL, ic, TRUE);
5295 freeAsmop (result, NULL, ic, TRUE);
5298 /*-----------------------------------------------------------------*/
5299 /* genGetHbit - generates code get highest order bit */
5300 /*-----------------------------------------------------------------*/
5302 genGetHbit (iCode * ic)
5304 operand *left, *result;
5305 left = IC_LEFT (ic);
5306 result = IC_RESULT (ic);
5307 aopOp (left, ic, FALSE);
5308 aopOp (result, ic, FALSE);
5310 /* get the highest order byte into a */
5311 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5312 if (AOP_TYPE (result) == AOP_CRY)
5314 emitcode ("rlc", "a");
5319 emitcode ("rl", "a");
5320 emitcode ("anl", "a,#0x01");
5325 freeAsmop (left, NULL, ic, TRUE);
5326 freeAsmop (result, NULL, ic, TRUE);
5329 /*-----------------------------------------------------------------*/
5330 /* AccRol - rotate left accumulator by known count */
5331 /*-----------------------------------------------------------------*/
5333 AccRol (int shCount)
5335 shCount &= 0x0007; // shCount : 0..7
5342 emitcode ("rl", "a");
5345 emitcode ("rl", "a");
5346 emitcode ("rl", "a");
5349 emitcode ("swap", "a");
5350 emitcode ("rr", "a");
5353 emitcode ("swap", "a");
5356 emitcode ("swap", "a");
5357 emitcode ("rl", "a");
5360 emitcode ("rr", "a");
5361 emitcode ("rr", "a");
5364 emitcode ("rr", "a");
5369 /*-----------------------------------------------------------------*/
5370 /* AccLsh - left shift accumulator by known count */
5371 /*-----------------------------------------------------------------*/
5373 AccLsh (int shCount)
5378 emitcode ("add", "a,acc");
5379 else if (shCount == 2)
5381 emitcode ("add", "a,acc");
5382 emitcode ("add", "a,acc");
5386 /* rotate left accumulator */
5388 /* and kill the lower order bits */
5389 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5394 /*-----------------------------------------------------------------*/
5395 /* AccRsh - right shift accumulator by known count */
5396 /*-----------------------------------------------------------------*/
5398 AccRsh (int shCount)
5405 emitcode ("rrc", "a");
5409 /* rotate right accumulator */
5410 AccRol (8 - shCount);
5411 /* and kill the higher order bits */
5412 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5417 /*-----------------------------------------------------------------*/
5418 /* AccSRsh - signed right shift accumulator by known count */
5419 /*-----------------------------------------------------------------*/
5421 AccSRsh (int shCount)
5428 emitcode ("mov", "c,acc.7");
5429 emitcode ("rrc", "a");
5431 else if (shCount == 2)
5433 emitcode ("mov", "c,acc.7");
5434 emitcode ("rrc", "a");
5435 emitcode ("mov", "c,acc.7");
5436 emitcode ("rrc", "a");
5440 tlbl = newiTempLabel (NULL);
5441 /* rotate right accumulator */
5442 AccRol (8 - shCount);
5443 /* and kill the higher order bits */
5444 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5445 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5446 emitcode ("orl", "a,#0x%02x",
5447 (unsigned char) ~SRMask[shCount]);
5448 emitcode ("", "%05d$:", tlbl->key + 100);
5453 /*-----------------------------------------------------------------*/
5454 /* shiftR1Left2Result - shift right one byte from left to result */
5455 /*-----------------------------------------------------------------*/
5457 shiftR1Left2Result (operand * left, int offl,
5458 operand * result, int offr,
5459 int shCount, int sign)
5461 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5462 /* shift right accumulator */
5467 aopPut (AOP (result), "a", offr);
5470 /*-----------------------------------------------------------------*/
5471 /* shiftL1Left2Result - shift left one byte from left to result */
5472 /*-----------------------------------------------------------------*/
5474 shiftL1Left2Result (operand * left, int offl,
5475 operand * result, int offr, int shCount)
5478 l = aopGet (AOP (left), offl, FALSE, FALSE);
5480 /* shift left accumulator */
5482 aopPut (AOP (result), "a", offr);
5485 /*-----------------------------------------------------------------*/
5486 /* movLeft2Result - move byte from left to result */
5487 /*-----------------------------------------------------------------*/
5489 movLeft2Result (operand * left, int offl,
5490 operand * result, int offr, int sign)
5493 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5495 l = aopGet (AOP (left), offl, FALSE, FALSE);
5497 if (*l == '@' && (IS_AOP_PREG (result)))
5499 emitcode ("mov", "a,%s", l);
5500 aopPut (AOP (result), "a", offr);
5505 aopPut (AOP (result), l, offr);
5508 /* MSB sign in acc.7 ! */
5509 if (getDataSize (left) == offl + 1)
5511 emitcode ("mov", "a,%s", l);
5512 aopPut (AOP (result), "a", offr);
5519 /*-----------------------------------------------------------------*/
5520 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5521 /*-----------------------------------------------------------------*/
5525 emitcode ("rrc", "a");
5526 emitcode ("xch", "a,%s", x);
5527 emitcode ("rrc", "a");
5528 emitcode ("xch", "a,%s", x);
5531 /*-----------------------------------------------------------------*/
5532 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5533 /*-----------------------------------------------------------------*/
5537 emitcode ("xch", "a,%s", x);
5538 emitcode ("rlc", "a");
5539 emitcode ("xch", "a,%s", x);
5540 emitcode ("rlc", "a");
5543 /*-----------------------------------------------------------------*/
5544 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5545 /*-----------------------------------------------------------------*/
5549 emitcode ("xch", "a,%s", x);
5550 emitcode ("add", "a,acc");
5551 emitcode ("xch", "a,%s", x);
5552 emitcode ("rlc", "a");
5555 /*-----------------------------------------------------------------*/
5556 /* AccAXLsh - left shift a:x by known count (0..7) */
5557 /*-----------------------------------------------------------------*/
5559 AccAXLsh (char *x, int shCount)
5574 case 5: // AAAAABBB:CCCCCDDD
5576 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5578 emitcode ("anl", "a,#0x%02x",
5579 SLMask[shCount]); // BBB00000:CCCCCDDD
5581 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5583 AccRol (shCount); // DDDCCCCC:BBB00000
5585 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5587 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5589 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5591 emitcode ("anl", "a,#0x%02x",
5592 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5594 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5596 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5599 case 6: // AAAAAABB:CCCCCCDD
5600 emitcode ("anl", "a,#0x%02x",
5601 SRMask[shCount]); // 000000BB:CCCCCCDD
5602 emitcode ("mov", "c,acc.0"); // c = B
5603 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5605 AccAXRrl1 (x); // BCCCCCCD:D000000B
5606 AccAXRrl1 (x); // BBCCCCCC:DD000000
5608 emitcode("rrc","a");
5609 emitcode("xch","a,%s", x);
5610 emitcode("rrc","a");
5611 emitcode("mov","c,acc.0"); //<< get correct bit
5612 emitcode("xch","a,%s", x);
5614 emitcode("rrc","a");
5615 emitcode("xch","a,%s", x);
5616 emitcode("rrc","a");
5617 emitcode("xch","a,%s", x);
5620 case 7: // a:x <<= 7
5622 emitcode ("anl", "a,#0x%02x",
5623 SRMask[shCount]); // 0000000B:CCCCCCCD
5625 emitcode ("mov", "c,acc.0"); // c = B
5627 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5629 AccAXRrl1 (x); // BCCCCCCC:D0000000
5637 /*-----------------------------------------------------------------*/
5638 /* AccAXRsh - right shift a:x known count (0..7) */
5639 /*-----------------------------------------------------------------*/
5641 AccAXRsh (char *x, int shCount)
5649 AccAXRrl1 (x); // 0->a:x
5654 AccAXRrl1 (x); // 0->a:x
5657 AccAXRrl1 (x); // 0->a:x
5662 case 5: // AAAAABBB:CCCCCDDD = a:x
5664 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5666 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5668 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5670 emitcode ("anl", "a,#0x%02x",
5671 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5673 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5675 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5677 emitcode ("anl", "a,#0x%02x",
5678 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5680 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5682 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5684 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5687 case 6: // AABBBBBB:CCDDDDDD
5689 emitcode ("mov", "c,acc.7");
5690 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5692 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5694 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5696 emitcode ("anl", "a,#0x%02x",
5697 SRMask[shCount]); // 000000AA:BBBBBBCC
5700 case 7: // ABBBBBBB:CDDDDDDD
5702 emitcode ("mov", "c,acc.7"); // c = A
5704 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5706 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5708 emitcode ("anl", "a,#0x%02x",
5709 SRMask[shCount]); // 0000000A:BBBBBBBC
5717 /*-----------------------------------------------------------------*/
5718 /* AccAXRshS - right shift signed a:x known count (0..7) */
5719 /*-----------------------------------------------------------------*/
5721 AccAXRshS (char *x, int shCount)
5729 emitcode ("mov", "c,acc.7");
5730 AccAXRrl1 (x); // s->a:x
5734 emitcode ("mov", "c,acc.7");
5735 AccAXRrl1 (x); // s->a:x
5737 emitcode ("mov", "c,acc.7");
5738 AccAXRrl1 (x); // s->a:x
5743 case 5: // AAAAABBB:CCCCCDDD = a:x
5745 tlbl = newiTempLabel (NULL);
5746 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5748 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5750 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5752 emitcode ("anl", "a,#0x%02x",
5753 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5755 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5757 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5759 emitcode ("anl", "a,#0x%02x",
5760 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5762 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5764 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5766 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5768 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5769 emitcode ("orl", "a,#0x%02x",
5770 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5772 emitcode ("", "%05d$:", tlbl->key + 100);
5773 break; // SSSSAAAA:BBBCCCCC
5775 case 6: // AABBBBBB:CCDDDDDD
5777 tlbl = newiTempLabel (NULL);
5778 emitcode ("mov", "c,acc.7");
5779 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5781 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5783 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5785 emitcode ("anl", "a,#0x%02x",
5786 SRMask[shCount]); // 000000AA:BBBBBBCC
5788 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5789 emitcode ("orl", "a,#0x%02x",
5790 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5792 emitcode ("", "%05d$:", tlbl->key + 100);
5794 case 7: // ABBBBBBB:CDDDDDDD
5796 tlbl = newiTempLabel (NULL);
5797 emitcode ("mov", "c,acc.7"); // c = A
5799 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5801 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5803 emitcode ("anl", "a,#0x%02x",
5804 SRMask[shCount]); // 0000000A:BBBBBBBC
5806 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5807 emitcode ("orl", "a,#0x%02x",
5808 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5810 emitcode ("", "%05d$:", tlbl->key + 100);
5817 /*-----------------------------------------------------------------*/
5818 /* shiftL2Left2Result - shift left two bytes from left to result */
5819 /*-----------------------------------------------------------------*/
5821 shiftL2Left2Result (operand * left, int offl,
5822 operand * result, int offr, int shCount)
5824 if (sameRegs (AOP (result), AOP (left)) &&
5825 ((offl + MSB16) == offr))
5827 /* don't crash result[offr] */
5828 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5829 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5833 movLeft2Result (left, offl, result, offr, 0);
5834 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5836 /* ax << shCount (x = lsb(result)) */
5837 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5838 aopPut (AOP (result), "a", offr + MSB16);
5842 /*-----------------------------------------------------------------*/
5843 /* shiftR2Left2Result - shift right two bytes from left to result */
5844 /*-----------------------------------------------------------------*/
5846 shiftR2Left2Result (operand * left, int offl,
5847 operand * result, int offr,
5848 int shCount, int sign)
5850 if (sameRegs (AOP (result), AOP (left)) &&
5851 ((offl + MSB16) == offr))
5853 /* don't crash result[offr] */
5854 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5855 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5859 movLeft2Result (left, offl, result, offr, 0);
5860 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5862 /* a:x >> shCount (x = lsb(result)) */
5864 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5866 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5867 if (getDataSize (result) > 1)
5868 aopPut (AOP (result), "a", offr + MSB16);
5871 /*-----------------------------------------------------------------*/
5872 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5873 /*-----------------------------------------------------------------*/
5875 shiftLLeftOrResult (operand * left, int offl,
5876 operand * result, int offr, int shCount)
5878 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5879 /* shift left accumulator */
5881 /* or with result */
5882 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5883 /* back to result */
5884 aopPut (AOP (result), "a", offr);
5887 /*-----------------------------------------------------------------*/
5888 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5889 /*-----------------------------------------------------------------*/
5891 shiftRLeftOrResult (operand * left, int offl,
5892 operand * result, int offr, int shCount)
5894 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5895 /* shift right accumulator */
5897 /* or with result */
5898 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5899 /* back to result */
5900 aopPut (AOP (result), "a", offr);
5903 /*-----------------------------------------------------------------*/
5904 /* genlshOne - left shift a one byte quantity by known count */
5905 /*-----------------------------------------------------------------*/
5907 genlshOne (operand * result, operand * left, int shCount)
5909 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5912 /*-----------------------------------------------------------------*/
5913 /* genlshTwo - left shift two bytes by known amount != 0 */
5914 /*-----------------------------------------------------------------*/
5916 genlshTwo (operand * result, operand * left, int shCount)
5920 size = getDataSize (result);
5922 /* if shCount >= 8 */
5930 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5932 movLeft2Result (left, LSB, result, MSB16, 0);
5934 aopPut (AOP (result), zero, LSB);
5937 /* 1 <= shCount <= 7 */
5941 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5943 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5947 /*-----------------------------------------------------------------*/
5948 /* shiftLLong - shift left one long from left to result */
5949 /* offl = LSB or MSB16 */
5950 /*-----------------------------------------------------------------*/
5952 shiftLLong (operand * left, operand * result, int offr)
5955 int size = AOP_SIZE (result);
5957 if (size >= LSB + offr)
5959 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5961 emitcode ("add", "a,acc");
5962 if (sameRegs (AOP (left), AOP (result)) &&
5963 size >= MSB16 + offr && offr != LSB)
5964 emitcode ("xch", "a,%s",
5965 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5967 aopPut (AOP (result), "a", LSB + offr);
5970 if (size >= MSB16 + offr)
5972 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5974 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5977 emitcode ("rlc", "a");
5978 if (sameRegs (AOP (left), AOP (result)) &&
5979 size >= MSB24 + offr && offr != LSB)
5980 emitcode ("xch", "a,%s",
5981 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5983 aopPut (AOP (result), "a", MSB16 + offr);
5986 if (size >= MSB24 + offr)
5988 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5990 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5993 emitcode ("rlc", "a");
5994 if (sameRegs (AOP (left), AOP (result)) &&
5995 size >= MSB32 + offr && offr != LSB)
5996 emitcode ("xch", "a,%s",
5997 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5999 aopPut (AOP (result), "a", MSB24 + offr);
6002 if (size > MSB32 + offr)
6004 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6006 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6009 emitcode ("rlc", "a");
6010 aopPut (AOP (result), "a", MSB32 + offr);
6013 aopPut (AOP (result), zero, LSB);
6016 /*-----------------------------------------------------------------*/
6017 /* genlshFour - shift four byte by a known amount != 0 */
6018 /*-----------------------------------------------------------------*/
6020 genlshFour (operand * result, operand * left, int shCount)
6024 size = AOP_SIZE (result);
6026 /* if shifting more that 3 bytes */
6031 /* lowest order of left goes to the highest
6032 order of the destination */
6033 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6035 movLeft2Result (left, LSB, result, MSB32, 0);
6036 aopPut (AOP (result), zero, LSB);
6037 aopPut (AOP (result), zero, MSB16);
6038 aopPut (AOP (result), zero, MSB24);
6042 /* more than two bytes */
6043 else if (shCount >= 16)
6045 /* lower order two bytes goes to higher order two bytes */
6047 /* if some more remaining */
6049 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6052 movLeft2Result (left, MSB16, result, MSB32, 0);
6053 movLeft2Result (left, LSB, result, MSB24, 0);
6055 aopPut (AOP (result), zero, MSB16);
6056 aopPut (AOP (result), zero, LSB);
6060 /* if more than 1 byte */
6061 else if (shCount >= 8)
6063 /* lower order three bytes goes to higher order three bytes */
6068 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6070 movLeft2Result (left, LSB, result, MSB16, 0);
6076 movLeft2Result (left, MSB24, result, MSB32, 0);
6077 movLeft2Result (left, MSB16, result, MSB24, 0);
6078 movLeft2Result (left, LSB, result, MSB16, 0);
6079 aopPut (AOP (result), zero, LSB);
6081 else if (shCount == 1)
6082 shiftLLong (left, result, MSB16);
6085 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6086 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6087 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6088 aopPut (AOP (result), zero, LSB);
6093 /* 1 <= shCount <= 7 */
6094 else if (shCount <= 2)
6096 shiftLLong (left, result, LSB);
6098 shiftLLong (result, result, LSB);
6100 /* 3 <= shCount <= 7, optimize */
6103 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6104 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6105 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6109 /*-----------------------------------------------------------------*/
6110 /* genLeftShiftLiteral - left shifting by known count */
6111 /*-----------------------------------------------------------------*/
6113 genLeftShiftLiteral (operand * left,
6118 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6121 freeAsmop (right, NULL, ic, TRUE);
6123 aopOp (left, ic, FALSE);
6124 aopOp (result, ic, FALSE);
6126 size = getSize (operandType (result));
6129 emitcode ("; shift left ", "result %d, left %d", size,
6133 /* I suppose that the left size >= result size */
6138 movLeft2Result (left, size, result, size, 0);
6142 else if (shCount >= (size * 8))
6144 aopPut (AOP (result), zero, size);
6150 genlshOne (result, left, shCount);
6154 genlshTwo (result, left, shCount);
6158 genlshFour (result, left, shCount);
6161 fprintf(stderr, "*** ack! mystery literal shift!\n");
6165 freeAsmop (left, NULL, ic, TRUE);
6166 freeAsmop (result, NULL, ic, TRUE);
6169 /*-----------------------------------------------------------------*/
6170 /* genLeftShift - generates code for left shifting */
6171 /*-----------------------------------------------------------------*/
6173 genLeftShift (iCode * ic)
6175 operand *left, *right, *result;
6178 symbol *tlbl, *tlbl1;
6180 right = IC_RIGHT (ic);
6181 left = IC_LEFT (ic);
6182 result = IC_RESULT (ic);
6184 aopOp (right, ic, FALSE);
6186 /* if the shift count is known then do it
6187 as efficiently as possible */
6188 if (AOP_TYPE (right) == AOP_LIT)
6190 genLeftShiftLiteral (left, right, result, ic);
6194 /* shift count is unknown then we have to form
6195 a loop get the loop count in B : Note: we take
6196 only the lower order byte since shifting
6197 more that 32 bits make no sense anyway, ( the
6198 largest size of an object can be only 32 bits ) */
6200 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6201 emitcode ("inc", "b");
6202 freeAsmop (right, NULL, ic, TRUE);
6203 aopOp (left, ic, FALSE);
6204 aopOp (result, ic, FALSE);
6206 /* now move the left to the result if they are not the
6208 if (!sameRegs (AOP (left), AOP (result)) &&
6209 AOP_SIZE (result) > 1)
6212 size = AOP_SIZE (result);
6216 l = aopGet (AOP (left), offset, FALSE, TRUE);
6217 if (*l == '@' && (IS_AOP_PREG (result)))
6220 emitcode ("mov", "a,%s", l);
6221 aopPut (AOP (result), "a", offset);
6224 aopPut (AOP (result), l, offset);
6229 tlbl = newiTempLabel (NULL);
6230 size = AOP_SIZE (result);
6232 tlbl1 = newiTempLabel (NULL);
6234 /* if it is only one byte then */
6237 symbol *tlbl1 = newiTempLabel (NULL);
6239 l = aopGet (AOP (left), 0, FALSE, FALSE);
6241 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6242 emitcode ("", "%05d$:", tlbl->key + 100);
6243 emitcode ("add", "a,acc");
6244 emitcode ("", "%05d$:", tlbl1->key + 100);
6245 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6246 aopPut (AOP (result), "a", 0);
6250 reAdjustPreg (AOP (result));
6252 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6253 emitcode ("", "%05d$:", tlbl->key + 100);
6254 l = aopGet (AOP (result), offset, FALSE, FALSE);
6256 emitcode ("add", "a,acc");
6257 aopPut (AOP (result), "a", offset++);
6260 l = aopGet (AOP (result), offset, FALSE, FALSE);
6262 emitcode ("rlc", "a");
6263 aopPut (AOP (result), "a", offset++);
6265 reAdjustPreg (AOP (result));
6267 emitcode ("", "%05d$:", tlbl1->key + 100);
6268 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6270 freeAsmop (left, NULL, ic, TRUE);
6271 freeAsmop (result, NULL, ic, TRUE);
6274 /*-----------------------------------------------------------------*/
6275 /* genrshOne - right shift a one byte quantity by known count */
6276 /*-----------------------------------------------------------------*/
6278 genrshOne (operand * result, operand * left,
6279 int shCount, int sign)
6281 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6284 /*-----------------------------------------------------------------*/
6285 /* genrshTwo - right shift two bytes by known amount != 0 */
6286 /*-----------------------------------------------------------------*/
6288 genrshTwo (operand * result, operand * left,
6289 int shCount, int sign)
6291 /* if shCount >= 8 */
6296 shiftR1Left2Result (left, MSB16, result, LSB,
6299 movLeft2Result (left, MSB16, result, LSB, sign);
6300 addSign (result, MSB16, sign);
6303 /* 1 <= shCount <= 7 */
6305 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6308 /*-----------------------------------------------------------------*/
6309 /* shiftRLong - shift right one long from left to result */
6310 /* offl = LSB or MSB16 */
6311 /*-----------------------------------------------------------------*/
6313 shiftRLong (operand * left, int offl,
6314 operand * result, int sign)
6316 int isSameRegs=sameRegs(AOP(left),AOP(result));
6318 if (isSameRegs && offl>1) {
6319 // we are in big trouble, but this shouldn't happen
6320 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6323 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6328 emitcode ("rlc", "a");
6329 emitcode ("subb", "a,acc");
6330 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6332 aopPut (AOP(result), zero, MSB32);
6337 emitcode ("clr", "c");
6339 emitcode ("mov", "c,acc.7");
6342 emitcode ("rrc", "a");
6344 if (isSameRegs && offl==MSB16) {
6345 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6347 aopPut (AOP (result), "a", MSB32);
6348 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6351 emitcode ("rrc", "a");
6352 if (isSameRegs && offl==1) {
6353 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6355 aopPut (AOP (result), "a", MSB24);
6356 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6358 emitcode ("rrc", "a");
6359 aopPut (AOP (result), "a", MSB16 - offl);
6363 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6364 emitcode ("rrc", "a");
6365 aopPut (AOP (result), "a", LSB);
6369 /*-----------------------------------------------------------------*/
6370 /* genrshFour - shift four byte by a known amount != 0 */
6371 /*-----------------------------------------------------------------*/
6373 genrshFour (operand * result, operand * left,
6374 int shCount, int sign)
6376 /* if shifting more that 3 bytes */
6381 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6383 movLeft2Result (left, MSB32, result, LSB, sign);
6384 addSign (result, MSB16, sign);
6386 else if (shCount >= 16)
6390 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6393 movLeft2Result (left, MSB24, result, LSB, 0);
6394 movLeft2Result (left, MSB32, result, MSB16, sign);
6396 addSign (result, MSB24, sign);
6398 else if (shCount >= 8)
6402 shiftRLong (left, MSB16, result, sign);
6403 else if (shCount == 0)
6405 movLeft2Result (left, MSB16, result, LSB, 0);
6406 movLeft2Result (left, MSB24, result, MSB16, 0);
6407 movLeft2Result (left, MSB32, result, MSB24, sign);
6408 addSign (result, MSB32, sign);
6412 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6413 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6414 /* the last shift is signed */
6415 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6416 addSign (result, MSB32, sign);
6420 { /* 1 <= shCount <= 7 */
6423 shiftRLong (left, LSB, result, sign);
6425 shiftRLong (result, LSB, result, sign);
6429 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6430 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6431 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6436 /*-----------------------------------------------------------------*/
6437 /* genRightShiftLiteral - right shifting by known count */
6438 /*-----------------------------------------------------------------*/
6440 genRightShiftLiteral (operand * left,
6446 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6449 freeAsmop (right, NULL, ic, TRUE);
6451 aopOp (left, ic, FALSE);
6452 aopOp (result, ic, FALSE);
6455 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6459 size = getDataSize (left);
6460 /* test the LEFT size !!! */
6462 /* I suppose that the left size >= result size */
6465 size = getDataSize (result);
6467 movLeft2Result (left, size, result, size, 0);
6470 else if (shCount >= (size * 8))
6473 /* get sign in acc.7 */
6474 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6475 addSign (result, LSB, sign);
6482 genrshOne (result, left, shCount, sign);
6486 genrshTwo (result, left, shCount, sign);
6490 genrshFour (result, left, shCount, sign);
6496 freeAsmop (left, NULL, ic, TRUE);
6497 freeAsmop (result, NULL, ic, TRUE);
6501 /*-----------------------------------------------------------------*/
6502 /* genSignedRightShift - right shift of signed number */
6503 /*-----------------------------------------------------------------*/
6505 genSignedRightShift (iCode * ic)
6507 operand *right, *left, *result;
6510 symbol *tlbl, *tlbl1;
6512 /* we do it the hard way put the shift count in b
6513 and loop thru preserving the sign */
6515 right = IC_RIGHT (ic);
6516 left = IC_LEFT (ic);
6517 result = IC_RESULT (ic);
6519 aopOp (right, ic, FALSE);
6522 if (AOP_TYPE (right) == AOP_LIT)
6524 genRightShiftLiteral (left, right, result, ic, 1);
6527 /* shift count is unknown then we have to form
6528 a loop get the loop count in B : Note: we take
6529 only the lower order byte since shifting
6530 more that 32 bits make no sense anyway, ( the
6531 largest size of an object can be only 32 bits ) */
6533 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6534 emitcode ("inc", "b");
6535 freeAsmop (right, NULL, ic, TRUE);
6536 aopOp (left, ic, FALSE);
6537 aopOp (result, ic, FALSE);
6539 /* now move the left to the result if they are not the
6541 if (!sameRegs (AOP (left), AOP (result)) &&
6542 AOP_SIZE (result) > 1)
6545 size = AOP_SIZE (result);
6549 l = aopGet (AOP (left), offset, FALSE, TRUE);
6550 if (*l == '@' && IS_AOP_PREG (result))
6553 emitcode ("mov", "a,%s", l);
6554 aopPut (AOP (result), "a", offset);
6557 aopPut (AOP (result), l, offset);
6562 /* mov the highest order bit to OVR */
6563 tlbl = newiTempLabel (NULL);
6564 tlbl1 = newiTempLabel (NULL);
6566 size = AOP_SIZE (result);
6568 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6569 emitcode ("rlc", "a");
6570 emitcode ("mov", "ov,c");
6571 /* if it is only one byte then */
6574 l = aopGet (AOP (left), 0, FALSE, FALSE);
6576 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6577 emitcode ("", "%05d$:", tlbl->key + 100);
6578 emitcode ("mov", "c,ov");
6579 emitcode ("rrc", "a");
6580 emitcode ("", "%05d$:", tlbl1->key + 100);
6581 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6582 aopPut (AOP (result), "a", 0);
6586 reAdjustPreg (AOP (result));
6587 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6588 emitcode ("", "%05d$:", tlbl->key + 100);
6589 emitcode ("mov", "c,ov");
6592 l = aopGet (AOP (result), offset, FALSE, FALSE);
6594 emitcode ("rrc", "a");
6595 aopPut (AOP (result), "a", offset--);
6597 reAdjustPreg (AOP (result));
6598 emitcode ("", "%05d$:", tlbl1->key + 100);
6599 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6602 freeAsmop (left, NULL, ic, TRUE);
6603 freeAsmop (result, NULL, ic, TRUE);
6606 /*-----------------------------------------------------------------*/
6607 /* genRightShift - generate code for right shifting */
6608 /*-----------------------------------------------------------------*/
6610 genRightShift (iCode * ic)
6612 operand *right, *left, *result;
6616 symbol *tlbl, *tlbl1;
6618 /* if signed then we do it the hard way preserve the
6619 sign bit moving it inwards */
6620 retype = getSpec (operandType (IC_RESULT (ic)));
6622 if (!SPEC_USIGN (retype))
6624 genSignedRightShift (ic);
6628 /* signed & unsigned types are treated the same : i.e. the
6629 signed is NOT propagated inwards : quoting from the
6630 ANSI - standard : "for E1 >> E2, is equivalent to division
6631 by 2**E2 if unsigned or if it has a non-negative value,
6632 otherwise the result is implementation defined ", MY definition
6633 is that the sign does not get propagated */
6635 right = IC_RIGHT (ic);
6636 left = IC_LEFT (ic);
6637 result = IC_RESULT (ic);
6639 aopOp (right, ic, FALSE);
6641 /* if the shift count is known then do it
6642 as efficiently as possible */
6643 if (AOP_TYPE (right) == AOP_LIT)
6645 genRightShiftLiteral (left, right, result, ic, 0);
6649 /* shift count is unknown then we have to form
6650 a loop get the loop count in B : Note: we take
6651 only the lower order byte since shifting
6652 more that 32 bits make no sense anyway, ( the
6653 largest size of an object can be only 32 bits ) */
6655 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6656 emitcode ("inc", "b");
6657 freeAsmop (right, NULL, ic, TRUE);
6658 aopOp (left, ic, FALSE);
6659 aopOp (result, ic, FALSE);
6661 /* now move the left to the result if they are not the
6663 if (!sameRegs (AOP (left), AOP (result)) &&
6664 AOP_SIZE (result) > 1)
6667 size = AOP_SIZE (result);
6671 l = aopGet (AOP (left), offset, FALSE, TRUE);
6672 if (*l == '@' && IS_AOP_PREG (result))
6675 emitcode ("mov", "a,%s", l);
6676 aopPut (AOP (result), "a", offset);
6679 aopPut (AOP (result), l, offset);
6684 tlbl = newiTempLabel (NULL);
6685 tlbl1 = newiTempLabel (NULL);
6686 size = AOP_SIZE (result);
6689 /* if it is only one byte then */
6692 l = aopGet (AOP (left), 0, FALSE, FALSE);
6694 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6695 emitcode ("", "%05d$:", tlbl->key + 100);
6697 emitcode ("rrc", "a");
6698 emitcode ("", "%05d$:", tlbl1->key + 100);
6699 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6700 aopPut (AOP (result), "a", 0);
6704 reAdjustPreg (AOP (result));
6705 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6706 emitcode ("", "%05d$:", tlbl->key + 100);
6710 l = aopGet (AOP (result), offset, FALSE, FALSE);
6712 emitcode ("rrc", "a");
6713 aopPut (AOP (result), "a", offset--);
6715 reAdjustPreg (AOP (result));
6717 emitcode ("", "%05d$:", tlbl1->key + 100);
6718 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6721 freeAsmop (left, NULL, ic, TRUE);
6722 freeAsmop (result, NULL, ic, TRUE);
6725 /*-----------------------------------------------------------------*/
6726 /* genUnpackBits - generates code for unpacking bits */
6727 /*-----------------------------------------------------------------*/
6729 genUnpackBits (operand * result, char *rname, int ptype)
6737 etype = getSpec (operandType (result));
6738 rsize = getSize (operandType (result));
6739 /* read the first byte */
6745 emitcode ("mov", "a,@%s", rname);
6749 emitcode ("movx", "a,@%s", rname);
6753 emitcode ("movx", "a,@dptr");
6757 emitcode ("clr", "a");
6758 emitcode ("movc", "a,%s", "@a+dptr");
6762 emitcode ("lcall", "__gptrget");
6766 rlen = SPEC_BLEN (etype);
6768 /* if we have bitdisplacement then it fits */
6769 /* into this byte completely or if length is */
6770 /* less than a byte */
6771 if ((shCnt = SPEC_BSTR (etype)) ||
6772 (SPEC_BLEN (etype) <= 8))
6775 /* shift right acc */
6778 emitcode ("anl", "a,#0x%02x",
6779 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6780 aopPut (AOP (result), "a", offset++);
6784 /* bit field did not fit in a byte */
6785 aopPut (AOP (result), "a", offset++);
6794 emitcode ("inc", "%s", rname);
6795 emitcode ("mov", "a,@%s", rname);
6799 emitcode ("inc", "%s", rname);
6800 emitcode ("movx", "a,@%s", rname);
6804 emitcode ("inc", "dptr");
6805 emitcode ("movx", "a,@dptr");
6809 emitcode ("clr", "a");
6810 emitcode ("inc", "dptr");
6811 emitcode ("movc", "a", "@a+dptr");
6815 emitcode ("inc", "dptr");
6816 emitcode ("lcall", "__gptrget");
6821 /* if we are done */
6825 aopPut (AOP (result), "a", offset++);
6831 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6833 aopPut (AOP (result), "a", offset++);
6841 aopPut (AOP (result), zero, offset++);
6847 /*-----------------------------------------------------------------*/
6848 /* genDataPointerGet - generates code when ptr offset is known */
6849 /*-----------------------------------------------------------------*/
6851 genDataPointerGet (operand * left,
6857 int size, offset = 0;
6858 aopOp (result, ic, TRUE);
6860 /* get the string representation of the name */
6861 l = aopGet (AOP (left), 0, FALSE, TRUE);
6862 size = AOP_SIZE (result);
6866 sprintf (buffer, "(%s + %d)", l + 1, offset);
6868 sprintf (buffer, "%s", l + 1);
6869 aopPut (AOP (result), buffer, offset++);
6872 freeAsmop (left, NULL, ic, TRUE);
6873 freeAsmop (result, NULL, ic, TRUE);
6876 /*-----------------------------------------------------------------*/
6877 /* genNearPointerGet - emitcode for near pointer fetch */
6878 /*-----------------------------------------------------------------*/
6880 genNearPointerGet (operand * left,
6888 sym_link *rtype, *retype;
6889 sym_link *ltype = operandType (left);
6892 rtype = operandType (result);
6893 retype = getSpec (rtype);
6895 aopOp (left, ic, FALSE);
6897 /* if left is rematerialisable and
6898 result is not bit variable type and
6899 the left is pointer to data space i.e
6900 lower 128 bytes of space */
6901 if (AOP_TYPE (left) == AOP_IMMD &&
6902 !IS_BITVAR (retype) &&
6903 DCL_TYPE (ltype) == POINTER)
6905 genDataPointerGet (left, result, ic);
6909 /* if the value is already in a pointer register
6910 then don't need anything more */
6911 if (!AOP_INPREG (AOP (left)))
6913 /* otherwise get a free pointer register */
6915 preg = getFreePtr (ic, &aop, FALSE);
6916 emitcode ("mov", "%s,%s",
6918 aopGet (AOP (left), 0, FALSE, TRUE));
6922 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6924 aopOp (result, ic, FALSE);
6926 /* if bitfield then unpack the bits */
6927 if (IS_BITVAR (retype))
6928 genUnpackBits (result, rname, POINTER);
6931 /* we have can just get the values */
6932 int size = AOP_SIZE (result);
6937 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6940 emitcode ("mov", "a,@%s", rname);
6941 aopPut (AOP (result), "a", offset);
6945 sprintf (buffer, "@%s", rname);
6946 aopPut (AOP (result), buffer, offset);
6950 emitcode ("inc", "%s", rname);
6954 /* now some housekeeping stuff */
6955 if (aop) /* we had to allocate for this iCode */
6957 if (pi) { /* post increment present */
6958 aopPut(AOP ( left ),rname,0);
6960 freeAsmop (NULL, aop, ic, TRUE);
6964 /* we did not allocate which means left
6965 already in a pointer register, then
6966 if size > 0 && this could be used again
6967 we have to point it back to where it
6969 if ((AOP_SIZE (result) > 1 &&
6970 !OP_SYMBOL (left)->remat &&
6971 (OP_SYMBOL (left)->liveTo > ic->seq ||
6975 int size = AOP_SIZE (result) - 1;
6977 emitcode ("dec", "%s", rname);
6982 freeAsmop (left, NULL, ic, TRUE);
6983 freeAsmop (result, NULL, ic, TRUE);
6984 if (pi) pi->generated = 1;
6987 /*-----------------------------------------------------------------*/
6988 /* genPagedPointerGet - emitcode for paged pointer fetch */
6989 /*-----------------------------------------------------------------*/
6991 genPagedPointerGet (operand * left,
6999 sym_link *rtype, *retype;
7001 rtype = operandType (result);
7002 retype = getSpec (rtype);
7004 aopOp (left, ic, FALSE);
7006 /* if the value is already in a pointer register
7007 then don't need anything more */
7008 if (!AOP_INPREG (AOP (left)))
7010 /* otherwise get a free pointer register */
7012 preg = getFreePtr (ic, &aop, FALSE);
7013 emitcode ("mov", "%s,%s",
7015 aopGet (AOP (left), 0, FALSE, TRUE));
7019 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7021 aopOp (result, ic, FALSE);
7023 /* if bitfield then unpack the bits */
7024 if (IS_BITVAR (retype))
7025 genUnpackBits (result, rname, PPOINTER);
7028 /* we have can just get the values */
7029 int size = AOP_SIZE (result);
7035 emitcode ("movx", "a,@%s", rname);
7036 aopPut (AOP (result), "a", offset);
7041 emitcode ("inc", "%s", rname);
7045 /* now some housekeeping stuff */
7046 if (aop) /* we had to allocate for this iCode */
7048 if (pi) aopPut ( AOP (left), rname, 0);
7049 freeAsmop (NULL, aop, ic, TRUE);
7053 /* we did not allocate which means left
7054 already in a pointer register, then
7055 if size > 0 && this could be used again
7056 we have to point it back to where it
7058 if ((AOP_SIZE (result) > 1 &&
7059 !OP_SYMBOL (left)->remat &&
7060 (OP_SYMBOL (left)->liveTo > ic->seq ||
7064 int size = AOP_SIZE (result) - 1;
7066 emitcode ("dec", "%s", rname);
7071 freeAsmop (left, NULL, ic, TRUE);
7072 freeAsmop (result, NULL, ic, TRUE);
7073 if (pi) pi->generated = 1;
7077 /*-----------------------------------------------------------------*/
7078 /* genFarPointerGet - gget value from far space */
7079 /*-----------------------------------------------------------------*/
7081 genFarPointerGet (operand * left,
7082 operand * result, iCode * ic, iCode * pi)
7085 sym_link *retype = getSpec (operandType (result));
7087 aopOp (left, ic, FALSE);
7089 /* if the operand is already in dptr
7090 then we do nothing else we move the value to dptr */
7091 if (AOP_TYPE (left) != AOP_STR)
7093 /* if this is remateriazable */
7094 if (AOP_TYPE (left) == AOP_IMMD)
7095 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7097 { /* we need to get it byte by byte */
7098 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7099 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7102 /* so dptr know contains the address */
7103 aopOp (result, ic, FALSE);
7105 /* if bit then unpack */
7106 if (IS_BITVAR (retype))
7107 genUnpackBits (result, "dptr", FPOINTER);
7110 size = AOP_SIZE (result);
7115 emitcode ("movx", "a,@dptr");
7116 aopPut (AOP (result), "a", offset++);
7118 emitcode ("inc", "dptr");
7122 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7123 aopPut ( AOP (left), "dpl", 0);
7124 aopPut ( AOP (left), "dph", 1);
7127 freeAsmop (left, NULL, ic, TRUE);
7128 freeAsmop (result, NULL, ic, TRUE);
7131 /*-----------------------------------------------------------------*/
7132 /* genCodePointerGet - gget value from code space */
7133 /*-----------------------------------------------------------------*/
7135 genCodePointerGet (operand * left,
7136 operand * result, iCode * ic, iCode *pi)
7139 sym_link *retype = getSpec (operandType (result));
7141 aopOp (left, ic, FALSE);
7143 /* if the operand is already in dptr
7144 then we do nothing else we move the value to dptr */
7145 if (AOP_TYPE (left) != AOP_STR)
7147 /* if this is remateriazable */
7148 if (AOP_TYPE (left) == AOP_IMMD)
7149 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7151 { /* we need to get it byte by byte */
7152 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7153 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7156 /* so dptr know contains the address */
7157 aopOp (result, ic, FALSE);
7159 /* if bit then unpack */
7160 if (IS_BITVAR (retype))
7161 genUnpackBits (result, "dptr", CPOINTER);
7164 size = AOP_SIZE (result);
7169 emitcode ("clr", "a");
7170 emitcode ("movc", "a,@a+dptr");
7171 aopPut (AOP (result), "a", offset++);
7173 emitcode ("inc", "dptr");
7177 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7178 aopPut ( AOP (left), "dpl", 0);
7179 aopPut ( AOP (left), "dph", 1);
7182 freeAsmop (left, NULL, ic, TRUE);
7183 freeAsmop (result, NULL, ic, TRUE);
7186 /*-----------------------------------------------------------------*/
7187 /* genGenPointerGet - gget value from generic pointer space */
7188 /*-----------------------------------------------------------------*/
7190 genGenPointerGet (operand * left,
7191 operand * result, iCode * ic, iCode *pi)
7194 sym_link *retype = getSpec (operandType (result));
7196 aopOp (left, ic, FALSE);
7198 /* if the operand is already in dptr
7199 then we do nothing else we move the value to dptr */
7200 if (AOP_TYPE (left) != AOP_STR)
7202 /* if this is remateriazable */
7203 if (AOP_TYPE (left) == AOP_IMMD)
7205 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7206 emitcode ("mov", "b,#%d", pointerCode (retype));
7209 { /* we need to get it byte by byte */
7210 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7211 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7212 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7215 /* so dptr know contains the address */
7216 aopOp (result, ic, FALSE);
7218 /* if bit then unpack */
7219 if (IS_BITVAR (retype))
7220 genUnpackBits (result, "dptr", GPOINTER);
7223 size = AOP_SIZE (result);
7228 emitcode ("lcall", "__gptrget");
7229 aopPut (AOP (result), "a", offset++);
7231 emitcode ("inc", "dptr");
7235 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7236 aopPut ( AOP (left), "dpl", 0);
7237 aopPut ( AOP (left), "dph", 1);
7240 freeAsmop (left, NULL, ic, TRUE);
7241 freeAsmop (result, NULL, ic, TRUE);
7244 /*-----------------------------------------------------------------*/
7245 /* genPointerGet - generate code for pointer get */
7246 /*-----------------------------------------------------------------*/
7248 genPointerGet (iCode * ic, iCode *pi)
7250 operand *left, *result;
7251 sym_link *type, *etype;
7254 left = IC_LEFT (ic);
7255 result = IC_RESULT (ic);
7257 /* depending on the type of pointer we need to
7258 move it to the correct pointer register */
7259 type = operandType (left);
7260 etype = getSpec (type);
7261 /* if left is of type of pointer then it is simple */
7262 if (IS_PTR (type) && !IS_FUNC (type->next))
7263 p_type = DCL_TYPE (type);
7266 /* we have to go by the storage class */
7267 p_type = PTR_TYPE (SPEC_OCLS (etype));
7270 /* now that we have the pointer type we assign
7271 the pointer values */
7277 genNearPointerGet (left, result, ic, pi);
7281 genPagedPointerGet (left, result, ic, pi);
7285 genFarPointerGet (left, result, ic, pi);
7289 genCodePointerGet (left, result, ic, pi);
7293 genGenPointerGet (left, result, ic, pi);
7299 /*-----------------------------------------------------------------*/
7300 /* genPackBits - generates code for packed bit storage */
7301 /*-----------------------------------------------------------------*/
7303 genPackBits (sym_link * etype,
7305 char *rname, int p_type)
7313 blen = SPEC_BLEN (etype);
7314 bstr = SPEC_BSTR (etype);
7316 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7319 /* if the bit lenth is less than or */
7320 /* it exactly fits a byte then */
7321 if (SPEC_BLEN (etype) <= 8)
7323 shCount = SPEC_BSTR (etype);
7325 /* shift left acc */
7328 if (SPEC_BLEN (etype) < 8)
7329 { /* if smaller than a byte */
7335 emitcode ("mov", "b,a");
7336 emitcode ("mov", "a,@%s", rname);
7340 emitcode ("mov", "b,a");
7341 emitcode ("movx", "a,@dptr");
7345 emitcode ("push", "b");
7346 emitcode ("push", "acc");
7347 emitcode ("lcall", "__gptrget");
7348 emitcode ("pop", "b");
7352 emitcode ("anl", "a,#0x%02x", (unsigned char)
7353 ((unsigned char) (0xFF << (blen + bstr)) |
7354 (unsigned char) (0xFF >> (8 - bstr))));
7355 emitcode ("orl", "a,b");
7356 if (p_type == GPOINTER)
7357 emitcode ("pop", "b");
7364 emitcode ("mov", "@%s,a", rname);
7368 emitcode ("movx", "@dptr,a");
7372 emitcode ("lcall", "__gptrput");
7377 if (SPEC_BLEN (etype) <= 8)
7380 emitcode ("inc", "%s", rname);
7381 rLen = SPEC_BLEN (etype);
7383 /* now generate for lengths greater than one byte */
7387 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7399 emitcode ("mov", "@%s,a", rname);
7402 emitcode ("mov", "@%s,%s", rname, l);
7407 emitcode ("movx", "@dptr,a");
7412 emitcode ("lcall", "__gptrput");
7415 emitcode ("inc", "%s", rname);
7420 /* last last was not complete */
7423 /* save the byte & read byte */
7427 emitcode ("mov", "b,a");
7428 emitcode ("mov", "a,@%s", rname);
7432 emitcode ("mov", "b,a");
7433 emitcode ("movx", "a,@dptr");
7437 emitcode ("push", "b");
7438 emitcode ("push", "acc");
7439 emitcode ("lcall", "__gptrget");
7440 emitcode ("pop", "b");
7444 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7445 emitcode ("orl", "a,b");
7448 if (p_type == GPOINTER)
7449 emitcode ("pop", "b");
7455 emitcode ("mov", "@%s,a", rname);
7459 emitcode ("movx", "@dptr,a");
7463 emitcode ("lcall", "__gptrput");
7467 /*-----------------------------------------------------------------*/
7468 /* genDataPointerSet - remat pointer to data space */
7469 /*-----------------------------------------------------------------*/
7471 genDataPointerSet (operand * right,
7475 int size, offset = 0;
7476 char *l, buffer[256];
7478 aopOp (right, ic, FALSE);
7480 l = aopGet (AOP (result), 0, FALSE, TRUE);
7481 size = AOP_SIZE (right);
7485 sprintf (buffer, "(%s + %d)", l + 1, offset);
7487 sprintf (buffer, "%s", l + 1);
7488 emitcode ("mov", "%s,%s", buffer,
7489 aopGet (AOP (right), offset++, FALSE, FALSE));
7492 freeAsmop (right, NULL, ic, TRUE);
7493 freeAsmop (result, NULL, ic, TRUE);
7496 /*-----------------------------------------------------------------*/
7497 /* genNearPointerSet - emitcode for near pointer put */
7498 /*-----------------------------------------------------------------*/
7500 genNearPointerSet (operand * right,
7508 sym_link *retype, *letype;
7509 sym_link *ptype = operandType (result);
7511 retype = getSpec (operandType (right));
7512 letype = getSpec (ptype);
7513 aopOp (result, ic, FALSE);
7515 /* if the result is rematerializable &
7516 in data space & not a bit variable */
7517 if (AOP_TYPE (result) == AOP_IMMD &&
7518 DCL_TYPE (ptype) == POINTER &&
7519 !IS_BITVAR (retype) &&
7520 !IS_BITVAR (letype))
7522 genDataPointerSet (right, result, ic);
7526 /* if the value is already in a pointer register
7527 then don't need anything more */
7528 if (!AOP_INPREG (AOP (result)))
7530 /* otherwise get a free pointer register */
7532 preg = getFreePtr (ic, &aop, FALSE);
7533 emitcode ("mov", "%s,%s",
7535 aopGet (AOP (result), 0, FALSE, TRUE));
7539 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7541 aopOp (right, ic, FALSE);
7543 /* if bitfield then unpack the bits */
7544 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7545 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7548 /* we have can just get the values */
7549 int size = AOP_SIZE (right);
7554 l = aopGet (AOP (right), offset, FALSE, TRUE);
7558 emitcode ("mov", "@%s,a", rname);
7561 emitcode ("mov", "@%s,%s", rname, l);
7563 emitcode ("inc", "%s", rname);
7568 /* now some housekeeping stuff */
7569 if (aop) /* we had to allocate for this iCode */
7571 if (pi) aopPut (AOP (result),rname,0);
7572 freeAsmop (NULL, aop, ic, TRUE);
7576 /* we did not allocate which means left
7577 already in a pointer register, then
7578 if size > 0 && this could be used again
7579 we have to point it back to where it
7581 if ((AOP_SIZE (right) > 1 &&
7582 !OP_SYMBOL (result)->remat &&
7583 (OP_SYMBOL (result)->liveTo > ic->seq ||
7587 int size = AOP_SIZE (right) - 1;
7589 emitcode ("dec", "%s", rname);
7594 if (pi) pi->generated = 1;
7595 freeAsmop (result, NULL, ic, TRUE);
7596 freeAsmop (right, NULL, ic, TRUE);
7599 /*-----------------------------------------------------------------*/
7600 /* genPagedPointerSet - emitcode for Paged pointer put */
7601 /*-----------------------------------------------------------------*/
7603 genPagedPointerSet (operand * right,
7611 sym_link *retype, *letype;
7613 retype = getSpec (operandType (right));
7614 letype = getSpec (operandType (result));
7616 aopOp (result, ic, FALSE);
7618 /* if the value is already in a pointer register
7619 then don't need anything more */
7620 if (!AOP_INPREG (AOP (result)))
7622 /* otherwise get a free pointer register */
7624 preg = getFreePtr (ic, &aop, FALSE);
7625 emitcode ("mov", "%s,%s",
7627 aopGet (AOP (result), 0, FALSE, TRUE));
7631 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7633 aopOp (right, ic, FALSE);
7635 /* if bitfield then unpack the bits */
7636 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7637 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7640 /* we have can just get the values */
7641 int size = AOP_SIZE (right);
7646 l = aopGet (AOP (right), offset, FALSE, TRUE);
7649 emitcode ("movx", "@%s,a", rname);
7652 emitcode ("inc", "%s", rname);
7658 /* now some housekeeping stuff */
7659 if (aop) /* we had to allocate for this iCode */
7661 if (pi) aopPut (AOP (result),rname,0);
7662 freeAsmop (NULL, aop, ic, TRUE);
7666 /* we did not allocate which means left
7667 already in a pointer register, then
7668 if size > 0 && this could be used again
7669 we have to point it back to where it
7671 if (AOP_SIZE (right) > 1 &&
7672 !OP_SYMBOL (result)->remat &&
7673 (OP_SYMBOL (result)->liveTo > ic->seq ||
7676 int size = AOP_SIZE (right) - 1;
7678 emitcode ("dec", "%s", rname);
7683 if (pi) pi->generated = 1;
7684 freeAsmop (result, NULL, ic, TRUE);
7685 freeAsmop (right, NULL, ic, TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genFarPointerSet - set value from far space */
7692 /*-----------------------------------------------------------------*/
7694 genFarPointerSet (operand * right,
7695 operand * result, iCode * ic, iCode * pi)
7698 sym_link *retype = getSpec (operandType (right));
7699 sym_link *letype = getSpec (operandType (result));
7700 aopOp (result, ic, FALSE);
7702 /* if the operand is already in dptr
7703 then we do nothing else we move the value to dptr */
7704 if (AOP_TYPE (result) != AOP_STR)
7706 /* if this is remateriazable */
7707 if (AOP_TYPE (result) == AOP_IMMD)
7708 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7710 { /* we need to get it byte by byte */
7711 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7712 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7715 /* so dptr know contains the address */
7716 aopOp (right, ic, FALSE);
7718 /* if bit then unpack */
7719 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7720 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7723 size = AOP_SIZE (right);
7728 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7730 emitcode ("movx", "@dptr,a");
7732 emitcode ("inc", "dptr");
7735 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7736 aopPut (AOP(result),"dpl",0);
7737 aopPut (AOP(result),"dph",1);
7740 freeAsmop (result, NULL, ic, TRUE);
7741 freeAsmop (right, NULL, ic, TRUE);
7744 /*-----------------------------------------------------------------*/
7745 /* genGenPointerSet - set value from generic pointer space */
7746 /*-----------------------------------------------------------------*/
7748 genGenPointerSet (operand * right,
7749 operand * result, iCode * ic, iCode * pi)
7752 sym_link *retype = getSpec (operandType (right));
7753 sym_link *letype = getSpec (operandType (result));
7755 aopOp (result, ic, FALSE);
7757 /* if the operand is already in dptr
7758 then we do nothing else we move the value to dptr */
7759 if (AOP_TYPE (result) != AOP_STR)
7761 /* if this is remateriazable */
7762 if (AOP_TYPE (result) == AOP_IMMD)
7764 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7765 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7768 { /* we need to get it byte by byte */
7769 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7770 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7771 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7774 /* so dptr know contains the address */
7775 aopOp (right, ic, FALSE);
7777 /* if bit then unpack */
7778 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7779 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7782 size = AOP_SIZE (right);
7787 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7789 emitcode ("lcall", "__gptrput");
7791 emitcode ("inc", "dptr");
7795 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7796 aopPut (AOP(result),"dpl",0);
7797 aopPut (AOP(result),"dph",1);
7800 freeAsmop (result, NULL, ic, TRUE);
7801 freeAsmop (right, NULL, ic, TRUE);
7804 /*-----------------------------------------------------------------*/
7805 /* genPointerSet - stores the value into a pointer location */
7806 /*-----------------------------------------------------------------*/
7808 genPointerSet (iCode * ic, iCode *pi)
7810 operand *right, *result;
7811 sym_link *type, *etype;
7814 right = IC_RIGHT (ic);
7815 result = IC_RESULT (ic);
7817 /* depending on the type of pointer we need to
7818 move it to the correct pointer register */
7819 type = operandType (result);
7820 etype = getSpec (type);
7821 /* if left is of type of pointer then it is simple */
7822 if (IS_PTR (type) && !IS_FUNC (type->next))
7824 p_type = DCL_TYPE (type);
7828 /* we have to go by the storage class */
7829 p_type = PTR_TYPE (SPEC_OCLS (etype));
7832 /* now that we have the pointer type we assign
7833 the pointer values */
7839 genNearPointerSet (right, result, ic, pi);
7843 genPagedPointerSet (right, result, ic, pi);
7847 genFarPointerSet (right, result, ic, pi);
7851 genGenPointerSet (right, result, ic, pi);
7857 /*-----------------------------------------------------------------*/
7858 /* genIfx - generate code for Ifx statement */
7859 /*-----------------------------------------------------------------*/
7861 genIfx (iCode * ic, iCode * popIc)
7863 operand *cond = IC_COND (ic);
7866 aopOp (cond, ic, FALSE);
7868 /* get the value into acc */
7869 if (AOP_TYPE (cond) != AOP_CRY)
7873 /* the result is now in the accumulator */
7874 freeAsmop (cond, NULL, ic, TRUE);
7876 /* if there was something to be popped then do it */
7880 /* if the condition is a bit variable */
7881 if (isbit && IS_ITEMP (cond) &&
7883 genIfxJump (ic, SPIL_LOC (cond)->rname);
7884 else if (isbit && !IS_ITEMP (cond))
7885 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7887 genIfxJump (ic, "a");
7892 /*-----------------------------------------------------------------*/
7893 /* genAddrOf - generates code for address of */
7894 /*-----------------------------------------------------------------*/
7896 genAddrOf (iCode * ic)
7898 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7901 aopOp (IC_RESULT (ic), ic, FALSE);
7903 /* if the operand is on the stack then we
7904 need to get the stack offset of this
7908 /* if it has an offset then we need to compute
7912 emitcode ("mov", "a,_bp");
7913 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7914 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7918 /* we can just move _bp */
7919 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7921 /* fill the result with zero */
7922 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7927 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7933 /* object not on stack then we need the name */
7934 size = AOP_SIZE (IC_RESULT (ic));
7939 char s[SDCC_NAME_MAX];
7941 sprintf (s, "#(%s >> %d)",
7945 sprintf (s, "#%s", sym->rname);
7946 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7950 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7954 /*-----------------------------------------------------------------*/
7955 /* genFarFarAssign - assignment when both are in far space */
7956 /*-----------------------------------------------------------------*/
7958 genFarFarAssign (operand * result, operand * right, iCode * ic)
7960 int size = AOP_SIZE (right);
7963 /* first push the right side on to the stack */
7966 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7968 emitcode ("push", "acc");
7971 freeAsmop (right, NULL, ic, FALSE);
7972 /* now assign DPTR to result */
7973 aopOp (result, ic, FALSE);
7974 size = AOP_SIZE (result);
7977 emitcode ("pop", "acc");
7978 aopPut (AOP (result), "a", --offset);
7980 freeAsmop (result, NULL, ic, FALSE);
7984 /*-----------------------------------------------------------------*/
7985 /* genAssign - generate code for assignment */
7986 /*-----------------------------------------------------------------*/
7988 genAssign (iCode * ic)
7990 operand *result, *right;
7992 unsigned long lit = 0L;
7994 result = IC_RESULT (ic);
7995 right = IC_RIGHT (ic);
7997 /* if they are the same */
7998 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8001 aopOp (right, ic, FALSE);
8003 /* special case both in far space */
8004 if (AOP_TYPE (right) == AOP_DPTR &&
8005 IS_TRUE_SYMOP (result) &&
8006 isOperandInFarSpace (result))
8009 genFarFarAssign (result, right, ic);
8013 aopOp (result, ic, TRUE);
8015 /* if they are the same registers */
8016 if (sameRegs (AOP (right), AOP (result)))
8019 /* if the result is a bit */
8020 if (AOP_TYPE (result) == AOP_CRY)
8023 /* if the right size is a literal then
8024 we know what the value is */
8025 if (AOP_TYPE (right) == AOP_LIT)
8027 if (((int) operandLitValue (right)))
8028 aopPut (AOP (result), one, 0);
8030 aopPut (AOP (result), zero, 0);
8034 /* the right is also a bit variable */
8035 if (AOP_TYPE (right) == AOP_CRY)
8037 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8038 aopPut (AOP (result), "c", 0);
8044 aopPut (AOP (result), "a", 0);
8048 /* bit variables done */
8050 size = AOP_SIZE (result);
8052 if (AOP_TYPE (right) == AOP_LIT)
8053 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8055 (AOP_TYPE (result) != AOP_REG) &&
8056 (AOP_TYPE (right) == AOP_LIT) &&
8057 !IS_FLOAT (operandType (right)) &&
8060 emitcode ("clr", "a");
8063 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8064 aopPut (AOP (result), "a", size);
8066 aopPut (AOP (result),
8067 aopGet (AOP (right), size, FALSE, FALSE),
8075 aopPut (AOP (result),
8076 aopGet (AOP (right), offset, FALSE, FALSE),
8083 freeAsmop (right, NULL, ic, TRUE);
8084 freeAsmop (result, NULL, ic, TRUE);
8087 /*-----------------------------------------------------------------*/
8088 /* genJumpTab - genrates code for jump table */
8089 /*-----------------------------------------------------------------*/
8091 genJumpTab (iCode * ic)
8096 aopOp (IC_JTCOND (ic), ic, FALSE);
8097 /* get the condition into accumulator */
8098 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8100 /* multiply by three */
8101 emitcode ("add", "a,acc");
8102 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8103 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8105 jtab = newiTempLabel (NULL);
8106 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8107 emitcode ("jmp", "@a+dptr");
8108 emitcode ("", "%05d$:", jtab->key + 100);
8109 /* now generate the jump labels */
8110 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8111 jtab = setNextItem (IC_JTLABELS (ic)))
8112 emitcode ("ljmp", "%05d$", jtab->key + 100);
8116 /*-----------------------------------------------------------------*/
8117 /* genCast - gen code for casting */
8118 /*-----------------------------------------------------------------*/
8120 genCast (iCode * ic)
8122 operand *result = IC_RESULT (ic);
8123 sym_link *ctype = operandType (IC_LEFT (ic));
8124 sym_link *rtype = operandType (IC_RIGHT (ic));
8125 operand *right = IC_RIGHT (ic);
8128 /* if they are equivalent then do nothing */
8129 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8132 aopOp (right, ic, FALSE);
8133 aopOp (result, ic, FALSE);
8135 /* if the result is a bit */
8136 if (AOP_TYPE (result) == AOP_CRY)
8138 /* if the right size is a literal then
8139 we know what the value is */
8140 if (AOP_TYPE (right) == AOP_LIT)
8142 if (((int) operandLitValue (right)))
8143 aopPut (AOP (result), one, 0);
8145 aopPut (AOP (result), zero, 0);
8150 /* the right is also a bit variable */
8151 if (AOP_TYPE (right) == AOP_CRY)
8153 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8154 aopPut (AOP (result), "c", 0);
8160 aopPut (AOP (result), "a", 0);
8164 /* if they are the same size : or less */
8165 if (AOP_SIZE (result) <= AOP_SIZE (right))
8168 /* if they are in the same place */
8169 if (sameRegs (AOP (right), AOP (result)))
8172 /* if they in different places then copy */
8173 size = AOP_SIZE (result);
8177 aopPut (AOP (result),
8178 aopGet (AOP (right), offset, FALSE, FALSE),
8186 /* if the result is of type pointer */
8191 sym_link *type = operandType (right);
8192 sym_link *etype = getSpec (type);
8194 /* pointer to generic pointer */
8195 if (IS_GENPTR (ctype))
8200 p_type = DCL_TYPE (type);
8203 if (SPEC_SCLS(etype)==S_REGISTER) {
8204 // let's assume it is a generic pointer
8207 /* we have to go by the storage class */
8208 p_type = PTR_TYPE (SPEC_OCLS (etype));
8212 /* the first two bytes are known */
8213 size = GPTRSIZE - 1;
8217 aopPut (AOP (result),
8218 aopGet (AOP (right), offset, FALSE, FALSE),
8222 /* the last byte depending on type */
8238 case PPOINTER: // what the fck is this?
8243 /* this should never happen */
8244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8245 "got unknown pointer type");
8248 aopPut (AOP (result), l, GPTRSIZE - 1);
8252 /* just copy the pointers */
8253 size = AOP_SIZE (result);
8257 aopPut (AOP (result),
8258 aopGet (AOP (right), offset, FALSE, FALSE),
8265 /* so we now know that the size of destination is greater
8266 than the size of the source */
8267 /* we move to result for the size of source */
8268 size = AOP_SIZE (right);
8272 aopPut (AOP (result),
8273 aopGet (AOP (right), offset, FALSE, FALSE),
8278 /* now depending on the sign of the source && destination */
8279 size = AOP_SIZE (result) - AOP_SIZE (right);
8280 /* if unsigned or not an integral type */
8281 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8284 aopPut (AOP (result), zero, offset++);
8288 /* we need to extend the sign :{ */
8289 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8292 emitcode ("rlc", "a");
8293 emitcode ("subb", "a,acc");
8295 aopPut (AOP (result), "a", offset++);
8298 /* we are done hurray !!!! */
8301 freeAsmop (right, NULL, ic, TRUE);
8302 freeAsmop (result, NULL, ic, TRUE);
8306 /*-----------------------------------------------------------------*/
8307 /* genDjnz - generate decrement & jump if not zero instrucion */
8308 /*-----------------------------------------------------------------*/
8310 genDjnz (iCode * ic, iCode * ifx)
8316 /* if the if condition has a false label
8317 then we cannot save */
8321 /* if the minus is not of the form
8323 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8324 !IS_OP_LITERAL (IC_RIGHT (ic)))
8327 if (operandLitValue (IC_RIGHT (ic)) != 1)
8330 /* if the size of this greater than one then no
8332 if (getSize (operandType (IC_RESULT (ic))) > 1)
8335 /* otherwise we can save BIG */
8336 lbl = newiTempLabel (NULL);
8337 lbl1 = newiTempLabel (NULL);
8339 aopOp (IC_RESULT (ic), ic, FALSE);
8341 if (AOP_NEEDSACC(IC_RESULT(ic)))
8343 /* If the result is accessed indirectly via
8344 * the accumulator, we must explicitly write
8345 * it back after the decrement.
8347 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8349 if (strcmp(rByte, "a"))
8351 /* Something is hopelessly wrong */
8352 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8353 __FILE__, __LINE__);
8354 /* We can just give up; the generated code will be inefficient,
8357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8360 emitcode ("dec", "%s", rByte);
8361 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8362 emitcode ("jnz", "%05d$", lbl->key + 100);
8364 else if (IS_AOP_PREG (IC_RESULT (ic)))
8366 emitcode ("dec", "%s",
8367 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8368 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8369 emitcode ("jnz", "%05d$", lbl->key + 100);
8373 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8376 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8377 emitcode ("", "%05d$:", lbl->key + 100);
8378 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8379 emitcode ("", "%05d$:", lbl1->key + 100);
8381 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8386 /*-----------------------------------------------------------------*/
8387 /* genReceive - generate code for a receive iCode */
8388 /*-----------------------------------------------------------------*/
8390 genReceive (iCode * ic)
8392 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8393 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8394 IS_TRUE_SYMOP (IC_RESULT (ic))))
8397 int size = getSize (operandType (IC_RESULT (ic)));
8398 int offset = fReturnSizeMCS51 - size;
8401 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8402 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8405 aopOp (IC_RESULT (ic), ic, FALSE);
8406 size = AOP_SIZE (IC_RESULT (ic));
8410 emitcode ("pop", "acc");
8411 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8418 aopOp (IC_RESULT (ic), ic, FALSE);
8420 assignResultValue (IC_RESULT (ic));
8423 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8426 /*-----------------------------------------------------------------*/
8427 /* gen51Code - generate code for 8051 based controllers */
8428 /*-----------------------------------------------------------------*/
8430 gen51Code (iCode * lic)
8435 lineHead = lineCurr = NULL;
8437 /* print the allocation information */
8439 printAllocInfo (currFunc, codeOutFile);
8440 /* if debug information required */
8441 /* if (options.debug && currFunc) { */
8444 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8446 if (IS_STATIC (currFunc->etype))
8447 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8449 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8452 /* stack pointer name */
8453 if (options.useXstack)
8459 for (ic = lic; ic; ic = ic->next)
8462 if (cln != ic->lineno)
8467 emitcode ("", "C$%s$%d$%d$%d ==.",
8468 FileBaseName (ic->filename), ic->lineno,
8469 ic->level, ic->block);
8472 emitcode (";", "%s %d", ic->filename, ic->lineno);
8475 /* if the result is marked as
8476 spilt and rematerializable or code for
8477 this has already been generated then
8479 if (resultRemat (ic) || ic->generated)
8482 /* depending on the operation */
8502 /* IPOP happens only when trying to restore a
8503 spilt live range, if there is an ifx statement
8504 following this pop then the if statement might
8505 be using some of the registers being popped which
8506 would destory the contents of the register so
8507 we need to check for this condition and handle it */
8509 ic->next->op == IFX &&
8510 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8511 genIfx (ic->next, ic);
8529 genEndFunction (ic);
8549 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8566 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8570 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8577 /* note these two are xlated by algebraic equivalence
8578 during parsing SDCC.y */
8579 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8580 "got '>=' or '<=' shouldn't have come here");
8584 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8596 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8600 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8604 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8631 case GET_VALUE_AT_ADDRESS:
8632 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8636 if (POINTER_SET (ic))
8637 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8663 addSet (&_G.sendSet, ic);
8672 /* now we are ready to call the
8673 peep hole optimizer */
8674 if (!options.nopeep)
8675 peepHole (&lineHead);
8677 /* now do the actual printing */
8678 printLine (lineHead, codeOutFile);