1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[INITIAL_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1451 /* find the registers in use at this time
1452 and push them away to safety */
1453 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1457 if (options.useXstack)
1459 if (bitVectBitValue (rsave, R0_IDX))
1460 emitcode ("mov", "b,r0");
1461 emitcode ("mov", "r0,%s", spname);
1462 for (i = 0; i < mcs51_nRegs; i++)
1464 if (bitVectBitValue (rsave, i))
1467 emitcode ("mov", "a,b");
1469 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1470 emitcode ("movx", "@r0,a");
1471 emitcode ("inc", "r0");
1474 emitcode ("mov", "%s,r0", spname);
1475 if (bitVectBitValue (rsave, R0_IDX))
1476 emitcode ("mov", "r0,b");
1479 for (i = 0; i < mcs51_nRegs; i++)
1481 if (bitVectBitValue (rsave, i))
1482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1485 detype = getSpec (operandType (IC_LEFT (ic)));
1487 #if 0 // why should we do this here??? jwk20011105
1489 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1490 IS_ISR (currFunc->etype) &&
1492 saveRBank (SPEC_BANK (detype), ic, TRUE);
1496 /*-----------------------------------------------------------------*/
1497 /* unsaveRegisters - pop the pushed registers */
1498 /*-----------------------------------------------------------------*/
1500 unsaveRegisters (iCode * ic)
1504 /* find the registers in use at this time
1505 and push them away to safety */
1506 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1509 if (options.useXstack)
1511 emitcode ("mov", "r0,%s", spname);
1512 for (i = mcs51_nRegs; i >= 0; i--)
1514 if (bitVectBitValue (rsave, i))
1516 emitcode ("dec", "r0");
1517 emitcode ("movx", "a,@r0");
1519 emitcode ("mov", "b,a");
1521 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = mcs51_nRegs; i >= 0; i--)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1539 /*-----------------------------------------------------------------*/
1541 /*-----------------------------------------------------------------*/
1543 pushSide (operand * oper, int size)
1548 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1549 if (AOP_TYPE (oper) != AOP_REG &&
1550 AOP_TYPE (oper) != AOP_DIR &&
1553 emitcode ("mov", "a,%s", l);
1554 emitcode ("push", "acc");
1557 emitcode ("push", "%s", l);
1561 /*-----------------------------------------------------------------*/
1562 /* assignResultValue - */
1563 /*-----------------------------------------------------------------*/
1565 assignResultValue (operand * oper)
1568 int size = AOP_SIZE (oper);
1571 aopPut (AOP (oper), fReturn[offset], offset);
1577 /*-----------------------------------------------------------------*/
1578 /* genXpush - pushes onto the external stack */
1579 /*-----------------------------------------------------------------*/
1581 genXpush (iCode * ic)
1583 asmop *aop = newAsmop (0);
1585 int size, offset = 0;
1587 aopOp (IC_LEFT (ic), ic, FALSE);
1588 r = getFreePtr (ic, &aop, FALSE);
1591 emitcode ("mov", "%s,_spx", r->name);
1593 size = AOP_SIZE (IC_LEFT (ic));
1597 char *l = aopGet (AOP (IC_LEFT (ic)),
1598 offset++, FALSE, FALSE);
1600 emitcode ("movx", "@%s,a", r->name);
1601 emitcode ("inc", "%s", r->name);
1606 emitcode ("mov", "_spx,%s", r->name);
1608 freeAsmop (NULL, aop, ic, TRUE);
1609 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1612 /*-----------------------------------------------------------------*/
1613 /* genIpush - genrate code for pushing this gets a little complex */
1614 /*-----------------------------------------------------------------*/
1616 genIpush (iCode * ic)
1618 int size, offset = 0;
1621 /* if this is not a parm push : ie. it is spill push
1622 and spill push is always done on the local stack */
1626 /* and the item is spilt then do nothing */
1627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1630 aopOp (IC_LEFT (ic), ic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (ic));
1632 /* push it on the stack */
1635 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1641 emitcode ("push", "%s", l);
1646 /* this is a paramter push: in this case we call
1647 the routine to find the call and save those
1648 registers that need to be saved */
1651 /* if use external stack then call the external
1652 stack pushing routine */
1653 if (options.useXstack)
1659 /* then do the push */
1660 aopOp (IC_LEFT (ic), ic, FALSE);
1663 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1664 size = AOP_SIZE (IC_LEFT (ic));
1668 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1669 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1670 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1673 emitcode ("mov", "a,%s", l);
1674 emitcode ("push", "acc");
1677 emitcode ("push", "%s", l);
1680 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1683 /*-----------------------------------------------------------------*/
1684 /* genIpop - recover the registers: can happen only for spilling */
1685 /*-----------------------------------------------------------------*/
1687 genIpop (iCode * ic)
1692 /* if the temp was not pushed then */
1693 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1696 aopOp (IC_LEFT (ic), ic, FALSE);
1697 size = AOP_SIZE (IC_LEFT (ic));
1698 offset = (size - 1);
1700 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1703 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* unsaveRBank - restores the resgister bank from stack */
1708 /*-----------------------------------------------------------------*/
1710 unsaveRBank (int bank, iCode * ic, bool popPsw)
1718 if (options.useXstack)
1722 werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
1723 "unexpected null IC in saveRBank");
1728 r = getFreePtr (ic, &aop, FALSE);
1731 emitcode ("mov", "%s,_spx", r->name);
1732 emitcode ("movx", "a,@%s", r->name);
1733 emitcode ("mov", "psw,a");
1734 emitcode ("dec", "%s", r->name);
1738 emitcode ("pop", "psw");
1741 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1743 if (options.useXstack)
1745 emitcode ("movx", "a,@%s", r->name);
1746 emitcode ("mov", "(%s+%d),a",
1747 regs8051[i].base, 8 * bank + regs8051[i].offset);
1748 emitcode ("dec", "%s", r->name);
1752 emitcode ("pop", "(%s+%d)",
1753 regs8051[i].base, 8 * bank + regs8051[i].offset);
1756 if (options.useXstack)
1759 emitcode ("mov", "_spx,%s", r->name);
1760 freeAsmop (NULL, aop, ic, TRUE);
1765 /*-----------------------------------------------------------------*/
1766 /* saveRBank - saves an entire register bank on the stack */
1767 /*-----------------------------------------------------------------*/
1769 saveRBank (int bank, iCode * ic, bool pushPsw)
1775 if (options.useXstack)
1779 werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
1780 "unexpected null IC in saveRBank");
1784 r = getFreePtr (ic, &aop, FALSE);
1785 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);
1811 freeAsmop (NULL, aop, ic, TRUE);
1816 emitcode ("push", "psw");
1819 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1828 /*-----------------------------------------------------------------*/
1829 /* genCall - generates a call statement */
1830 /*-----------------------------------------------------------------*/
1832 genCall (iCode * ic)
1835 bool restoreBank = FALSE;
1836 bool swapBanks = FALSE;
1838 /* if send set is not empty the assign */
1843 for (sic = setFirstItem (_G.sendSet); sic;
1844 sic = setNextItem (_G.sendSet))
1846 int size, offset = 0;
1847 aopOp (IC_LEFT (sic), sic, FALSE);
1848 size = AOP_SIZE (IC_LEFT (sic));
1851 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1853 if (strcmp (l, fReturn[offset]))
1854 emitcode ("mov", "%s,%s",
1859 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1864 /* if we are calling a function that is not using
1865 the same register bank then we need to save the
1866 destination registers on the stack */
1867 detype = getSpec (operandType (IC_LEFT (ic)));
1869 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1870 IS_ISR (currFunc->etype))
1874 /* This is unexpected; the bank should have been saved in
1877 saveRBank (SPEC_BANK (detype), ic, FALSE);
1883 /* if caller saves & we have not saved then */
1889 emitcode ("mov", "psw,#0x%02x",
1890 ((SPEC_BANK(detype)) << 3) & 0xff);
1894 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1895 OP_SYMBOL (IC_LEFT (ic))->rname :
1896 OP_SYMBOL (IC_LEFT (ic))->name));
1900 emitcode ("mov", "psw,#0x%02x",
1901 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1904 /* if we need assign a result value */
1905 if ((IS_ITEMP (IC_RESULT (ic)) &&
1906 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1907 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1908 IS_TRUE_SYMOP (IC_RESULT (ic)))
1912 aopOp (IC_RESULT (ic), ic, FALSE);
1915 assignResultValue (IC_RESULT (ic));
1917 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1920 /* adjust the stack for parameters if
1925 if (ic->parmBytes > 3)
1927 emitcode ("mov", "a,%s", spname);
1928 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1929 emitcode ("mov", "%s,a", spname);
1932 for (i = 0; i < ic->parmBytes; i++)
1933 emitcode ("dec", "%s", spname);
1936 /* if we hade saved some registers then unsave them */
1937 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1938 unsaveRegisters (ic);
1940 /* if register bank was saved then pop them */
1942 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1945 /*-----------------------------------------------------------------*/
1946 /* genPcall - generates a call by pointer statement */
1947 /*-----------------------------------------------------------------*/
1949 genPcall (iCode * ic)
1952 symbol *rlbl = newiTempLabel (NULL);
1955 /* if caller saves & we have not saved then */
1959 /* if we are calling a function that is not using
1960 the same register bank then we need to save the
1961 destination registers on the stack */
1962 detype = getSpec (operandType (IC_LEFT (ic)));
1964 IS_ISR (currFunc->etype) &&
1965 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1966 saveRBank (SPEC_BANK (detype), ic, TRUE);
1969 /* push the return address on to the stack */
1970 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1971 emitcode ("push", "acc");
1972 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1973 emitcode ("push", "acc");
1975 /* now push the calling address */
1976 aopOp (IC_LEFT (ic), ic, FALSE);
1978 pushSide (IC_LEFT (ic), FPTRSIZE);
1980 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1982 /* if send set is not empty the assign */
1987 for (sic = setFirstItem (_G.sendSet); sic;
1988 sic = setNextItem (_G.sendSet))
1990 int size, offset = 0;
1991 aopOp (IC_LEFT (sic), sic, FALSE);
1992 size = AOP_SIZE (IC_LEFT (sic));
1995 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1997 if (strcmp (l, fReturn[offset]))
1998 emitcode ("mov", "%s,%s",
2003 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2008 emitcode ("ret", "");
2009 emitcode ("", "%05d$:", (rlbl->key + 100));
2012 /* if we need assign a result value */
2013 if ((IS_ITEMP (IC_RESULT (ic)) &&
2014 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2015 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2016 IS_TRUE_SYMOP (IC_RESULT (ic)))
2020 aopOp (IC_RESULT (ic), ic, FALSE);
2023 assignResultValue (IC_RESULT (ic));
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2028 /* adjust the stack for parameters if
2033 if (ic->parmBytes > 3)
2035 emitcode ("mov", "a,%s", spname);
2036 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2037 emitcode ("mov", "%s,a", spname);
2040 for (i = 0; i < ic->parmBytes; i++)
2041 emitcode ("dec", "%s", spname);
2045 /* if register bank was saved then unsave them */
2047 (SPEC_BANK (currFunc->etype) !=
2048 SPEC_BANK (detype)))
2049 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2051 /* if we hade saved some registers then
2054 unsaveRegisters (ic);
2058 /*-----------------------------------------------------------------*/
2059 /* resultRemat - result is rematerializable */
2060 /*-----------------------------------------------------------------*/
2062 resultRemat (iCode * ic)
2064 if (SKIP_IC (ic) || ic->op == IFX)
2067 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2069 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2070 if (sym->remat && !POINTER_SET (ic))
2077 #if defined(__BORLANDC__) || defined(_MSC_VER)
2078 #define STRCASECMP stricmp
2080 #define STRCASECMP strcasecmp
2083 /*-----------------------------------------------------------------*/
2084 /* inExcludeList - return 1 if the string is in exclude Reg list */
2085 /*-----------------------------------------------------------------*/
2087 inExcludeList (char *s)
2091 if (options.excludeRegs[i] &&
2092 STRCASECMP (options.excludeRegs[i], "none") == 0)
2095 for (i = 0; options.excludeRegs[i]; i++)
2097 if (options.excludeRegs[i] &&
2098 STRCASECMP (s, options.excludeRegs[i]) == 0)
2104 /*-----------------------------------------------------------------*/
2105 /* genFunction - generated code for function entry */
2106 /*-----------------------------------------------------------------*/
2108 genFunction (iCode * ic)
2114 /* create the function header */
2115 emitcode (";", "-----------------------------------------");
2116 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2117 emitcode (";", "-----------------------------------------");
2119 emitcode ("", "%s:", sym->rname);
2120 fetype = getSpec (operandType (IC_LEFT (ic)));
2122 /* if critical function then turn interrupts off */
2123 if (SPEC_CRTCL (fetype))
2124 emitcode ("clr", "ea");
2126 /* here we need to generate the equates for the
2127 register bank if required */
2128 if (SPEC_BANK (fetype) != rbank)
2132 rbank = SPEC_BANK (fetype);
2133 for (i = 0; i < mcs51_nRegs; i++)
2135 if (strcmp (regs8051[i].base, "0") == 0)
2136 emitcode ("", "%s = 0x%02x",
2138 8 * rbank + regs8051[i].offset);
2140 emitcode ("", "%s = %s + 0x%02x",
2143 8 * rbank + regs8051[i].offset);
2147 /* if this is an interrupt service routine then
2148 save acc, b, dpl, dph */
2149 if (IS_ISR (sym->etype))
2152 if (!inExcludeList ("acc"))
2153 emitcode ("push", "acc");
2154 if (!inExcludeList ("b"))
2155 emitcode ("push", "b");
2156 if (!inExcludeList ("dpl"))
2157 emitcode ("push", "dpl");
2158 if (!inExcludeList ("dph"))
2159 emitcode ("push", "dph");
2160 /* if this isr has no bank i.e. is going to
2161 run with bank 0 , then we need to save more
2163 if (!SPEC_BANK (sym->etype))
2166 /* if this function does not call any other
2167 function then we can be economical and
2168 save only those registers that are used */
2173 /* if any registers used */
2176 /* save the registers used */
2177 for (i = 0; i < sym->regsUsed->size; i++)
2179 if (bitVectBitValue (sym->regsUsed, i) ||
2180 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2181 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2188 /* this function has a function call cannot
2189 determines register usage so we will have to push the
2191 saveRBank (0, ic, FALSE);
2196 /* This ISR uses a non-zero bank.
2198 * We assume that the bank is available for our
2201 * However, if this ISR calls a function which uses some
2202 * other bank, we must save that bank entirely.
2204 unsigned long banksToSave = 0;
2209 #define MAX_REGISTER_BANKS 4
2214 for (i = ic; i; i = i->next)
2216 if (i->op == ENDFUNCTION)
2218 /* we got to the end OK. */
2226 detype = getSpec(operandType (IC_LEFT(i)));
2228 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2230 /* Mark this bank for saving. */
2231 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2233 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2237 banksToSave |= (1 << SPEC_BANK(detype));
2240 /* And note that we don't need to do it in
2248 /* This is a mess; we have no idea what
2249 * register bank the called function might
2252 * The only thing I can think of to do is
2253 * throw a warning and hope.
2255 werror(W_FUNCPTR_IN_USING_ISR);
2259 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2261 if (banksToSave & (1 << ix))
2263 saveRBank(ix, NULL, FALSE);
2267 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2272 /* if callee-save to be used for this function
2273 then save the registers being used in this function */
2274 if (sym->calleeSave)
2278 /* if any registers used */
2281 /* save the registers used */
2282 for (i = 0; i < sym->regsUsed->size; i++)
2284 if (bitVectBitValue (sym->regsUsed, i) ||
2285 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2287 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2295 /* set the register bank to the desired value */
2296 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2298 emitcode ("push", "psw");
2299 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2302 if (IS_RENT (sym->etype) || options.stackAuto)
2305 if (options.useXstack)
2307 emitcode ("mov", "r0,%s", spname);
2308 emitcode ("mov", "a,_bp");
2309 emitcode ("movx", "@r0,a");
2310 emitcode ("inc", "%s", spname);
2314 /* set up the stack */
2315 emitcode ("push", "_bp"); /* save the callers stack */
2317 emitcode ("mov", "_bp,%s", spname);
2320 /* adjust the stack for the function */
2326 werror (W_STACK_OVERFLOW, sym->name);
2328 if (i > 3 && sym->recvSize < 4)
2331 emitcode ("mov", "a,sp");
2332 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2333 emitcode ("mov", "sp,a");
2338 emitcode ("inc", "sp");
2344 emitcode ("mov", "a,_spx");
2345 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2346 emitcode ("mov", "_spx,a");
2351 /*-----------------------------------------------------------------*/
2352 /* genEndFunction - generates epilogue for functions */
2353 /*-----------------------------------------------------------------*/
2355 genEndFunction (iCode * ic)
2357 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2359 if (IS_RENT (sym->etype) || options.stackAuto)
2361 emitcode ("mov", "%s,_bp", spname);
2364 /* if use external stack but some variables were
2365 added to the local stack then decrement the
2367 if (options.useXstack && sym->stack)
2369 emitcode ("mov", "a,sp");
2370 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2371 emitcode ("mov", "sp,a");
2375 if ((IS_RENT (sym->etype) || options.stackAuto))
2377 if (options.useXstack)
2379 emitcode ("mov", "r0,%s", spname);
2380 emitcode ("movx", "a,@r0");
2381 emitcode ("mov", "_bp,a");
2382 emitcode ("dec", "%s", spname);
2386 emitcode ("pop", "_bp");
2390 /* restore the register bank */
2391 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2392 emitcode ("pop", "psw");
2394 if (IS_ISR (sym->etype))
2397 /* now we need to restore the registers */
2398 /* if this isr has no bank i.e. is going to
2399 run with bank 0 , then we need to save more
2401 if (!SPEC_BANK (sym->etype))
2404 /* if this function does not call any other
2405 function then we can be economical and
2406 save only those registers that are used */
2411 /* if any registers used */
2414 /* save the registers used */
2415 for (i = sym->regsUsed->size; i >= 0; i--)
2417 if (bitVectBitValue (sym->regsUsed, i) ||
2418 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2419 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2426 /* this function has a function call cannot
2427 determines register usage so we will have to pop the
2429 unsaveRBank (0, ic, FALSE);
2434 /* This ISR uses a non-zero bank.
2436 * Restore any register banks saved by genFunction
2439 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2442 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2444 if (savedBanks & (1 << ix))
2446 unsaveRBank(ix, NULL, FALSE);
2451 if (!inExcludeList ("dph"))
2452 emitcode ("pop", "dph");
2453 if (!inExcludeList ("dpl"))
2454 emitcode ("pop", "dpl");
2455 if (!inExcludeList ("b"))
2456 emitcode ("pop", "b");
2457 if (!inExcludeList ("acc"))
2458 emitcode ("pop", "acc");
2460 if (SPEC_CRTCL (sym->etype))
2461 emitcode ("setb", "ea");
2463 /* if debug then send end of function */
2464 /* if (options.debug && currFunc) { */
2468 emitcode ("", "C$%s$%d$%d$%d ==.",
2469 FileBaseName (ic->filename), currFunc->lastLine,
2470 ic->level, ic->block);
2471 if (IS_STATIC (currFunc->etype))
2472 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2474 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2478 emitcode ("reti", "");
2482 if (SPEC_CRTCL (sym->etype))
2483 emitcode ("setb", "ea");
2485 if (sym->calleeSave)
2489 /* if any registers used */
2492 /* save the registers used */
2493 for (i = sym->regsUsed->size; i >= 0; i--)
2495 if (bitVectBitValue (sym->regsUsed, i) ||
2496 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2497 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2503 /* if debug then send end of function */
2507 emitcode ("", "C$%s$%d$%d$%d ==.",
2508 FileBaseName (ic->filename), currFunc->lastLine,
2509 ic->level, ic->block);
2510 if (IS_STATIC (currFunc->etype))
2511 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2513 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2517 emitcode ("ret", "");
2522 /*-----------------------------------------------------------------*/
2523 /* genRet - generate code for return statement */
2524 /*-----------------------------------------------------------------*/
2528 int size, offset = 0, pushed = 0;
2530 /* if we have no return value then
2531 just generate the "ret" */
2535 /* we have something to return then
2536 move the return value into place */
2537 aopOp (IC_LEFT (ic), ic, FALSE);
2538 size = AOP_SIZE (IC_LEFT (ic));
2543 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2546 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2548 emitcode ("push", "%s", l);
2553 l = aopGet (AOP (IC_LEFT (ic)), offset,
2555 if (strcmp (fReturn[offset], l))
2556 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2565 if (strcmp (fReturn[pushed], "a"))
2566 emitcode ("pop", fReturn[pushed]);
2568 emitcode ("pop", "acc");
2571 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2574 /* generate a jump to the return label
2575 if the next is not the return statement */
2576 if (!(ic->next && ic->next->op == LABEL &&
2577 IC_LABEL (ic->next) == returnLabel))
2579 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2583 /*-----------------------------------------------------------------*/
2584 /* genLabel - generates a label */
2585 /*-----------------------------------------------------------------*/
2587 genLabel (iCode * ic)
2589 /* special case never generate */
2590 if (IC_LABEL (ic) == entryLabel)
2593 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2596 /*-----------------------------------------------------------------*/
2597 /* genGoto - generates a ljmp */
2598 /*-----------------------------------------------------------------*/
2600 genGoto (iCode * ic)
2602 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2605 /*-----------------------------------------------------------------*/
2606 /* findLabelBackwards: walks back through the iCode chain looking */
2607 /* for the given label. Returns number of iCode instructions */
2608 /* between that label and given ic. */
2609 /* Returns zero if label not found. */
2610 /*-----------------------------------------------------------------*/
2612 findLabelBackwards (iCode * ic, int key)
2621 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2623 /* printf("findLabelBackwards = %d\n", count); */
2631 /*-----------------------------------------------------------------*/
2632 /* genPlusIncr :- does addition with increment if possible */
2633 /*-----------------------------------------------------------------*/
2635 genPlusIncr (iCode * ic)
2637 unsigned int icount;
2638 unsigned int size = getDataSize (IC_RESULT (ic));
2640 /* will try to generate an increment */
2641 /* if the right side is not a literal
2643 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2646 /* if the literal value of the right hand side
2647 is greater than 4 then it is not worth it */
2648 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2651 /* if increment 16 bits in register */
2652 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2660 /* If the next instruction is a goto and the goto target
2661 * is < 10 instructions previous to this, we can generate
2662 * jumps straight to that target.
2664 if (ic->next && ic->next->op == GOTO
2665 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2666 && labelRange <= 10)
2668 emitcode (";", "tail increment optimized");
2669 tlbl = IC_LABEL (ic->next);
2674 tlbl = newiTempLabel (NULL);
2677 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2678 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2679 IS_AOP_PREG (IC_RESULT (ic)))
2680 emitcode ("cjne", "%s,#0x00,%05d$"
2681 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2685 emitcode ("clr", "a");
2686 emitcode ("cjne", "a,%s,%05d$"
2687 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2691 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2694 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2695 IS_AOP_PREG (IC_RESULT (ic)))
2696 emitcode ("cjne", "%s,#0x00,%05d$"
2697 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2700 emitcode ("cjne", "a,%s,%05d$"
2701 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2704 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2708 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2709 IS_AOP_PREG (IC_RESULT (ic)))
2710 emitcode ("cjne", "%s,#0x00,%05d$"
2711 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2715 emitcode ("cjne", "a,%s,%05d$"
2716 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2719 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2724 emitcode ("", "%05d$:", tlbl->key + 100);
2729 /* if the sizes are greater than 1 then we cannot */
2730 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2731 AOP_SIZE (IC_LEFT (ic)) > 1)
2734 /* we can if the aops of the left & result match or
2735 if they are in registers and the registers are the
2737 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2742 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2743 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2744 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2750 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2759 /*-----------------------------------------------------------------*/
2760 /* outBitAcc - output a bit in acc */
2761 /*-----------------------------------------------------------------*/
2763 outBitAcc (operand * result)
2765 symbol *tlbl = newiTempLabel (NULL);
2766 /* if the result is a bit */
2767 if (AOP_TYPE (result) == AOP_CRY)
2769 aopPut (AOP (result), "a", 0);
2773 emitcode ("jz", "%05d$", tlbl->key + 100);
2774 emitcode ("mov", "a,%s", one);
2775 emitcode ("", "%05d$:", tlbl->key + 100);
2780 /*-----------------------------------------------------------------*/
2781 /* genPlusBits - generates code for addition of two bits */
2782 /*-----------------------------------------------------------------*/
2784 genPlusBits (iCode * ic)
2786 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2788 symbol *lbl = newiTempLabel (NULL);
2789 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2790 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2791 emitcode ("cpl", "c");
2792 emitcode ("", "%05d$:", (lbl->key + 100));
2793 outBitC (IC_RESULT (ic));
2797 emitcode ("clr", "a");
2798 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2799 emitcode ("rlc", "a");
2800 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2801 emitcode ("addc", "a,#0x00");
2802 outAcc (IC_RESULT (ic));
2807 /* This is the original version of this code.
2809 * This is being kept around for reference,
2810 * because I am not entirely sure I got it right...
2813 adjustArithmeticResult (iCode * ic)
2815 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2816 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2817 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2818 aopPut (AOP (IC_RESULT (ic)),
2819 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2822 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2823 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2824 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2825 aopPut (AOP (IC_RESULT (ic)),
2826 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2829 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2830 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2831 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2832 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2833 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2836 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2837 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2841 /* This is the pure and virtuous version of this code.
2842 * I'm pretty certain it's right, but not enough to toss the old
2846 adjustArithmeticResult (iCode * ic)
2848 if (opIsGptr (IC_RESULT (ic)) &&
2849 opIsGptr (IC_LEFT (ic)) &&
2850 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2852 aopPut (AOP (IC_RESULT (ic)),
2853 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2857 if (opIsGptr (IC_RESULT (ic)) &&
2858 opIsGptr (IC_RIGHT (ic)) &&
2859 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2861 aopPut (AOP (IC_RESULT (ic)),
2862 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2866 if (opIsGptr (IC_RESULT (ic)) &&
2867 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2868 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2869 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2870 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2873 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2874 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2879 /*-----------------------------------------------------------------*/
2880 /* genPlus - generates code for addition */
2881 /*-----------------------------------------------------------------*/
2883 genPlus (iCode * ic)
2885 int size, offset = 0;
2887 /* special cases :- */
2889 aopOp (IC_LEFT (ic), ic, FALSE);
2890 aopOp (IC_RIGHT (ic), ic, FALSE);
2891 aopOp (IC_RESULT (ic), ic, TRUE);
2893 /* if literal, literal on the right or
2894 if left requires ACC or right is already
2896 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2897 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2898 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2900 operand *t = IC_RIGHT (ic);
2901 IC_RIGHT (ic) = IC_LEFT (ic);
2905 /* if both left & right are in bit
2907 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2908 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2914 /* if left in bit space & right literal */
2915 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2916 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2918 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2919 /* if result in bit space */
2920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2922 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2923 emitcode ("cpl", "c");
2924 outBitC (IC_RESULT (ic));
2928 size = getDataSize (IC_RESULT (ic));
2931 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2932 emitcode ("addc", "a,#00");
2933 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2939 /* if I can do an increment instead
2940 of add then GOOD for ME */
2941 if (genPlusIncr (ic) == TRUE)
2944 size = getDataSize (IC_RESULT (ic));
2948 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2950 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2952 emitcode ("add", "a,%s",
2953 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2955 emitcode ("addc", "a,%s",
2956 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2960 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2962 emitcode ("add", "a,%s",
2963 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2965 emitcode ("addc", "a,%s",
2966 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2968 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2971 adjustArithmeticResult (ic);
2974 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2975 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2976 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2979 /*-----------------------------------------------------------------*/
2980 /* genMinusDec :- does subtraction with deccrement if possible */
2981 /*-----------------------------------------------------------------*/
2983 genMinusDec (iCode * ic)
2985 unsigned int icount;
2986 unsigned int size = getDataSize (IC_RESULT (ic));
2988 /* will try to generate an increment */
2989 /* if the right side is not a literal
2991 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2994 /* if the literal value of the right hand side
2995 is greater than 4 then it is not worth it */
2996 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2999 /* if decrement 16 bits in register */
3000 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3008 /* If the next instruction is a goto and the goto target
3009 * is <= 10 instructions previous to this, we can generate
3010 * jumps straight to that target.
3012 if (ic->next && ic->next->op == GOTO
3013 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3014 && labelRange <= 10)
3016 emitcode (";", "tail decrement optimized");
3017 tlbl = IC_LABEL (ic->next);
3022 tlbl = newiTempLabel (NULL);
3026 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3027 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3028 IS_AOP_PREG (IC_RESULT (ic)))
3029 emitcode ("cjne", "%s,#0xff,%05d$"
3030 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3034 emitcode ("mov", "a,#0xff");
3035 emitcode ("cjne", "a,%s,%05d$"
3036 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3039 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3042 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3043 IS_AOP_PREG (IC_RESULT (ic)))
3044 emitcode ("cjne", "%s,#0xff,%05d$"
3045 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3049 emitcode ("cjne", "a,%s,%05d$"
3050 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3053 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3057 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3058 IS_AOP_PREG (IC_RESULT (ic)))
3059 emitcode ("cjne", "%s,#0xff,%05d$"
3060 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3064 emitcode ("cjne", "a,%s,%05d$"
3065 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3068 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3072 emitcode ("", "%05d$:", tlbl->key + 100);
3077 /* if the sizes are greater than 1 then we cannot */
3078 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3079 AOP_SIZE (IC_LEFT (ic)) > 1)
3082 /* we can if the aops of the left & result match or
3083 if they are in registers and the registers are the
3085 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3089 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3097 /*-----------------------------------------------------------------*/
3098 /* addSign - complete with sign */
3099 /*-----------------------------------------------------------------*/
3101 addSign (operand * result, int offset, int sign)
3103 int size = (getDataSize (result) - offset);
3108 emitcode ("rlc", "a");
3109 emitcode ("subb", "a,acc");
3111 aopPut (AOP (result), "a", offset++);
3115 aopPut (AOP (result), zero, offset++);
3119 /*-----------------------------------------------------------------*/
3120 /* genMinusBits - generates code for subtraction of two bits */
3121 /*-----------------------------------------------------------------*/
3123 genMinusBits (iCode * ic)
3125 symbol *lbl = newiTempLabel (NULL);
3126 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3128 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3129 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3130 emitcode ("cpl", "c");
3131 emitcode ("", "%05d$:", (lbl->key + 100));
3132 outBitC (IC_RESULT (ic));
3136 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3137 emitcode ("subb", "a,acc");
3138 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3139 emitcode ("inc", "a");
3140 emitcode ("", "%05d$:", (lbl->key + 100));
3141 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3142 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3146 /*-----------------------------------------------------------------*/
3147 /* genMinus - generates code for subtraction */
3148 /*-----------------------------------------------------------------*/
3150 genMinus (iCode * ic)
3152 int size, offset = 0;
3153 unsigned long lit = 0L;
3155 aopOp (IC_LEFT (ic), ic, FALSE);
3156 aopOp (IC_RIGHT (ic), ic, FALSE);
3157 aopOp (IC_RESULT (ic), ic, TRUE);
3159 /* special cases :- */
3160 /* if both left & right are in bit space */
3161 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3162 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3168 /* if I can do an decrement instead
3169 of subtract then GOOD for ME */
3170 if (genMinusDec (ic) == TRUE)
3173 size = getDataSize (IC_RESULT (ic));
3175 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3181 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3185 /* if literal, add a,#-lit, else normal subb */
3188 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3189 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3190 emitcode ("subb", "a,%s",
3191 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3194 /* first add without previous c */
3196 emitcode ("add", "a,#0x%02x",
3197 (unsigned int) (lit & 0x0FFL));
3199 emitcode ("addc", "a,#0x%02x",
3200 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3202 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3205 adjustArithmeticResult (ic);
3208 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3209 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3214 /*-----------------------------------------------------------------*/
3215 /* genMultbits :- multiplication of bits */
3216 /*-----------------------------------------------------------------*/
3218 genMultbits (operand * left,
3222 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3223 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3228 /*-----------------------------------------------------------------*/
3229 /* genMultOneByte : 8*8=8/16 bit multiplication */
3230 /*-----------------------------------------------------------------*/
3232 genMultOneByte (operand * left,
3236 sym_link *opetype = operandType (result);
3238 int size=AOP_SIZE(result);
3240 //emitcode (";",__FUNCTION__);
3241 if (size<1 || size>2) {
3242 // this should never happen
3243 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3244 AOP_SIZE(result), __FILE__, lineno);
3248 /* (if two literals: the value is computed before) */
3249 /* if one literal, literal on the right */
3250 if (AOP_TYPE (left) == AOP_LIT)
3255 //emitcode (";", "swapped left and right");
3258 if (SPEC_USIGN(opetype)
3259 // ignore the sign of left and right, what else can we do?
3260 || (SPEC_USIGN(operandType(left)) &&
3261 SPEC_USIGN(operandType(right)))) {
3262 // just an unsigned 8*8=8/16 multiply
3263 //emitcode (";","unsigned");
3264 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3265 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3266 emitcode ("mul", "ab");
3267 aopPut (AOP (result), "a", 0);
3269 aopPut (AOP (result), "b", 1);
3274 // we have to do a signed multiply
3276 //emitcode (";", "signed");
3277 emitcode ("clr", "F0"); // reset sign flag
3278 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3279 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3281 lbl=newiTempLabel(NULL);
3282 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3283 // left side is negative, 8-bit two's complement, this fails for -128
3284 emitcode ("setb", "F0"); // set sign flag
3285 emitcode ("cpl", "a");
3286 emitcode ("inc", "a");
3288 emitcode ("", "%05d$:", lbl->key+100);
3289 emitcode ("xch", "a,b");
3292 if (AOP_TYPE(right)==AOP_LIT) {
3293 /* AND literal negative */
3294 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3295 // two's complement for literal<0
3296 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3297 emitcode ("cpl", "a");
3298 emitcode ("inc", "a");
3301 lbl=newiTempLabel(NULL);
3302 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3303 // right side is negative, 8-bit two's complement
3304 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3305 emitcode ("cpl", "a");
3306 emitcode ("inc", "a");
3307 emitcode ("", "%05d$:", lbl->key+100);
3309 emitcode ("mul", "ab");
3311 lbl=newiTempLabel(NULL);
3312 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3313 // only ONE op was negative, we have to do a 8/16-bit two's complement
3314 emitcode ("cpl", "a"); // lsb
3316 emitcode ("inc", "a");
3318 emitcode ("add", "a,#1");
3319 emitcode ("xch", "a,b");
3320 emitcode ("cpl", "a"); // msb
3321 emitcode ("addc", "a,#0");
3322 emitcode ("xch", "a,b");
3325 emitcode ("", "%05d$:", lbl->key+100);
3326 aopPut (AOP (result), "a", 0);
3328 aopPut (AOP (result), "b", 1);
3332 /*-----------------------------------------------------------------*/
3333 /* genMult - generates code for multiplication */
3334 /*-----------------------------------------------------------------*/
3336 genMult (iCode * ic)
3338 operand *left = IC_LEFT (ic);
3339 operand *right = IC_RIGHT (ic);
3340 operand *result = IC_RESULT (ic);
3342 /* assign the amsops */
3343 aopOp (left, ic, FALSE);
3344 aopOp (right, ic, FALSE);
3345 aopOp (result, ic, TRUE);
3347 /* special cases first */
3349 if (AOP_TYPE (left) == AOP_CRY &&
3350 AOP_TYPE (right) == AOP_CRY)
3352 genMultbits (left, right, result);
3356 /* if both are of size == 1 */
3357 if (AOP_SIZE (left) == 1 &&
3358 AOP_SIZE (right) == 1)
3360 genMultOneByte (left, right, result);
3364 /* should have been converted to function call */
3368 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3369 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3370 freeAsmop (result, NULL, ic, TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* genDivbits :- division of bits */
3375 /*-----------------------------------------------------------------*/
3377 genDivbits (operand * left,
3384 /* the result must be bit */
3385 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3386 l = aopGet (AOP (left), 0, FALSE, FALSE);
3390 emitcode ("div", "ab");
3391 emitcode ("rrc", "a");
3392 aopPut (AOP (result), "c", 0);
3395 /*-----------------------------------------------------------------*/
3396 /* genDivOneByte : 8 bit division */
3397 /*-----------------------------------------------------------------*/
3399 genDivOneByte (operand * left,
3403 sym_link *opetype = operandType (result);
3408 size = AOP_SIZE (result) - 1;
3410 /* signed or unsigned */
3411 if (SPEC_USIGN (opetype))
3413 /* unsigned is easy */
3414 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3415 l = aopGet (AOP (left), 0, FALSE, FALSE);
3417 emitcode ("div", "ab");
3418 aopPut (AOP (result), "a", 0);
3420 aopPut (AOP (result), zero, offset++);
3424 /* signed is a little bit more difficult */
3426 /* save the signs of the operands */
3427 l = aopGet (AOP (left), 0, FALSE, FALSE);
3429 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3430 emitcode ("push", "acc"); /* save it on the stack */
3432 /* now sign adjust for both left & right */
3433 l = aopGet (AOP (right), 0, FALSE, FALSE);
3435 lbl = newiTempLabel (NULL);
3436 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3437 emitcode ("cpl", "a");
3438 emitcode ("inc", "a");
3439 emitcode ("", "%05d$:", (lbl->key + 100));
3440 emitcode ("mov", "b,a");
3442 /* sign adjust left side */
3443 l = aopGet (AOP (left), 0, FALSE, FALSE);
3446 lbl = newiTempLabel (NULL);
3447 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3448 emitcode ("cpl", "a");
3449 emitcode ("inc", "a");
3450 emitcode ("", "%05d$:", (lbl->key + 100));
3452 /* now the division */
3453 emitcode ("div", "ab");
3454 /* we are interested in the lower order
3456 emitcode ("mov", "b,a");
3457 lbl = newiTempLabel (NULL);
3458 emitcode ("pop", "acc");
3459 /* if there was an over flow we don't
3460 adjust the sign of the result */
3461 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3462 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3464 emitcode ("clr", "a");
3465 emitcode ("subb", "a,b");
3466 emitcode ("mov", "b,a");
3467 emitcode ("", "%05d$:", (lbl->key + 100));
3469 /* now we are done */
3470 aopPut (AOP (result), "b", 0);
3473 emitcode ("mov", "c,b.7");
3474 emitcode ("subb", "a,acc");
3477 aopPut (AOP (result), "a", offset++);
3481 /*-----------------------------------------------------------------*/
3482 /* genDiv - generates code for division */
3483 /*-----------------------------------------------------------------*/
3487 operand *left = IC_LEFT (ic);
3488 operand *right = IC_RIGHT (ic);
3489 operand *result = IC_RESULT (ic);
3491 /* assign the amsops */
3492 aopOp (left, ic, FALSE);
3493 aopOp (right, ic, FALSE);
3494 aopOp (result, ic, TRUE);
3496 /* special cases first */
3498 if (AOP_TYPE (left) == AOP_CRY &&
3499 AOP_TYPE (right) == AOP_CRY)
3501 genDivbits (left, right, result);
3505 /* if both are of size == 1 */
3506 if (AOP_SIZE (left) == 1 &&
3507 AOP_SIZE (right) == 1)
3509 genDivOneByte (left, right, result);
3513 /* should have been converted to function call */
3516 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3517 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3518 freeAsmop (result, NULL, ic, TRUE);
3521 /*-----------------------------------------------------------------*/
3522 /* genModbits :- modulus of bits */
3523 /*-----------------------------------------------------------------*/
3525 genModbits (operand * left,
3532 /* the result must be bit */
3533 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3534 l = aopGet (AOP (left), 0, FALSE, FALSE);
3538 emitcode ("div", "ab");
3539 emitcode ("mov", "a,b");
3540 emitcode ("rrc", "a");
3541 aopPut (AOP (result), "c", 0);
3544 /*-----------------------------------------------------------------*/
3545 /* genModOneByte : 8 bit modulus */
3546 /*-----------------------------------------------------------------*/
3548 genModOneByte (operand * left,
3552 sym_link *opetype = operandType (result);
3556 /* signed or unsigned */
3557 if (SPEC_USIGN (opetype))
3559 /* unsigned is easy */
3560 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3561 l = aopGet (AOP (left), 0, FALSE, FALSE);
3563 emitcode ("div", "ab");
3564 aopPut (AOP (result), "b", 0);
3568 /* signed is a little bit more difficult */
3570 /* save the signs of the operands */
3571 l = aopGet (AOP (left), 0, FALSE, FALSE);
3574 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3575 emitcode ("push", "acc"); /* save it on the stack */
3577 /* now sign adjust for both left & right */
3578 l = aopGet (AOP (right), 0, FALSE, FALSE);
3581 lbl = newiTempLabel (NULL);
3582 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3583 emitcode ("cpl", "a");
3584 emitcode ("inc", "a");
3585 emitcode ("", "%05d$:", (lbl->key + 100));
3586 emitcode ("mov", "b,a");
3588 /* sign adjust left side */
3589 l = aopGet (AOP (left), 0, FALSE, FALSE);
3592 lbl = newiTempLabel (NULL);
3593 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3594 emitcode ("cpl", "a");
3595 emitcode ("inc", "a");
3596 emitcode ("", "%05d$:", (lbl->key + 100));
3598 /* now the multiplication */
3599 emitcode ("div", "ab");
3600 /* we are interested in the lower order
3602 lbl = newiTempLabel (NULL);
3603 emitcode ("pop", "acc");
3604 /* if there was an over flow we don't
3605 adjust the sign of the result */
3606 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3607 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3609 emitcode ("clr", "a");
3610 emitcode ("subb", "a,b");
3611 emitcode ("mov", "b,a");
3612 emitcode ("", "%05d$:", (lbl->key + 100));
3614 /* now we are done */
3615 aopPut (AOP (result), "b", 0);
3619 /*-----------------------------------------------------------------*/
3620 /* genMod - generates code for division */
3621 /*-----------------------------------------------------------------*/
3625 operand *left = IC_LEFT (ic);
3626 operand *right = IC_RIGHT (ic);
3627 operand *result = IC_RESULT (ic);
3629 /* assign the amsops */
3630 aopOp (left, ic, FALSE);
3631 aopOp (right, ic, FALSE);
3632 aopOp (result, ic, TRUE);
3634 /* special cases first */
3636 if (AOP_TYPE (left) == AOP_CRY &&
3637 AOP_TYPE (right) == AOP_CRY)
3639 genModbits (left, right, result);
3643 /* if both are of size == 1 */
3644 if (AOP_SIZE (left) == 1 &&
3645 AOP_SIZE (right) == 1)
3647 genModOneByte (left, right, result);
3651 /* should have been converted to function call */
3655 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3656 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3657 freeAsmop (result, NULL, ic, TRUE);
3660 /*-----------------------------------------------------------------*/
3661 /* genIfxJump :- will create a jump depending on the ifx */
3662 /*-----------------------------------------------------------------*/
3664 genIfxJump (iCode * ic, char *jval)
3667 symbol *tlbl = newiTempLabel (NULL);
3670 /* if true label then we jump if condition
3674 jlbl = IC_TRUE (ic);
3675 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3676 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3680 /* false label is present */
3681 jlbl = IC_FALSE (ic);
3682 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3683 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3685 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3686 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3688 emitcode (inst, "%05d$", tlbl->key + 100);
3689 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3690 emitcode ("", "%05d$:", tlbl->key + 100);
3692 /* mark the icode as generated */
3696 /*-----------------------------------------------------------------*/
3697 /* genCmp :- greater or less than comparison */
3698 /*-----------------------------------------------------------------*/
3700 genCmp (operand * left, operand * right,
3701 operand * result, iCode * ifx, int sign, iCode *ic)
3703 int size, offset = 0;
3704 unsigned long lit = 0L;
3706 /* if left & right are bit variables */
3707 if (AOP_TYPE (left) == AOP_CRY &&
3708 AOP_TYPE (right) == AOP_CRY)
3710 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3711 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3715 /* subtract right from left if at the
3716 end the carry flag is set then we know that
3717 left is greater than right */
3718 size = max (AOP_SIZE (left), AOP_SIZE (right));
3720 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3721 if ((size == 1) && !sign &&
3722 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3724 symbol *lbl = newiTempLabel (NULL);
3725 emitcode ("cjne", "%s,%s,%05d$",
3726 aopGet (AOP (left), offset, FALSE, FALSE),
3727 aopGet (AOP (right), offset, FALSE, FALSE),
3729 emitcode ("", "%05d$:", lbl->key + 100);
3733 if (AOP_TYPE (right) == AOP_LIT)
3735 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3736 /* optimize if(x < 0) or if(x >= 0) */
3745 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3746 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3748 genIfxJump (ifx, "acc.7");
3752 emitcode ("rlc", "a");
3760 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3761 if (sign && size == 0)
3763 emitcode ("xrl", "a,#0x80");
3764 if (AOP_TYPE (right) == AOP_LIT)
3766 unsigned long lit = (unsigned long)
3767 floatFromVal (AOP (right)->aopu.aop_lit);
3768 emitcode ("subb", "a,#0x%02x",
3769 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3773 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3774 emitcode ("xrl", "b,#0x80");
3775 emitcode ("subb", "a,b");
3779 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3785 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3786 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3787 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3793 /* if the result is used in the next
3794 ifx conditional branch then generate
3795 code a little differently */
3797 genIfxJump (ifx, "c");
3800 /* leave the result in acc */
3804 /*-----------------------------------------------------------------*/
3805 /* genCmpGt :- greater than comparison */
3806 /*-----------------------------------------------------------------*/
3808 genCmpGt (iCode * ic, iCode * ifx)
3810 operand *left, *right, *result;
3811 sym_link *letype, *retype;
3814 left = IC_LEFT (ic);
3815 right = IC_RIGHT (ic);
3816 result = IC_RESULT (ic);
3818 letype = getSpec (operandType (left));
3819 retype = getSpec (operandType (right));
3820 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3821 /* assign the amsops */
3822 aopOp (left, ic, FALSE);
3823 aopOp (right, ic, FALSE);
3824 aopOp (result, ic, TRUE);
3826 genCmp (right, left, result, ifx, sign,ic);
3828 freeAsmop (result, NULL, ic, TRUE);
3831 /*-----------------------------------------------------------------*/
3832 /* genCmpLt - less than comparisons */
3833 /*-----------------------------------------------------------------*/
3835 genCmpLt (iCode * ic, iCode * ifx)
3837 operand *left, *right, *result;
3838 sym_link *letype, *retype;
3841 left = IC_LEFT (ic);
3842 right = IC_RIGHT (ic);
3843 result = IC_RESULT (ic);
3845 letype = getSpec (operandType (left));
3846 retype = getSpec (operandType (right));
3847 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3849 /* assign the amsops */
3850 aopOp (left, ic, FALSE);
3851 aopOp (right, ic, FALSE);
3852 aopOp (result, ic, TRUE);
3854 genCmp (left, right, result, ifx, sign,ic);
3856 freeAsmop (result, NULL, ic, TRUE);
3859 /*-----------------------------------------------------------------*/
3860 /* gencjneshort - compare and jump if not equal */
3861 /*-----------------------------------------------------------------*/
3863 gencjneshort (operand * left, operand * right, symbol * lbl)
3865 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3867 unsigned long lit = 0L;
3869 /* if the left side is a literal or
3870 if the right is in a pointer register and left
3872 if ((AOP_TYPE (left) == AOP_LIT) ||
3873 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3879 if (AOP_TYPE (right) == AOP_LIT)
3880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3882 /* if the right side is a literal then anything goes */
3883 if (AOP_TYPE (right) == AOP_LIT &&
3884 AOP_TYPE (left) != AOP_DIR)
3888 emitcode ("cjne", "%s,%s,%05d$",
3889 aopGet (AOP (left), offset, FALSE, FALSE),
3890 aopGet (AOP (right), offset, FALSE, FALSE),
3896 /* if the right side is in a register or in direct space or
3897 if the left is a pointer register & right is not */
3898 else if (AOP_TYPE (right) == AOP_REG ||
3899 AOP_TYPE (right) == AOP_DIR ||
3900 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3901 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3905 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3906 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3907 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3908 emitcode ("jnz", "%05d$", lbl->key + 100);
3910 emitcode ("cjne", "a,%s,%05d$",
3911 aopGet (AOP (right), offset, FALSE, TRUE),
3918 /* right is a pointer reg need both a & b */
3921 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3922 if (strcmp (l, "b"))
3923 emitcode ("mov", "b,%s", l);
3924 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3925 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3931 /*-----------------------------------------------------------------*/
3932 /* gencjne - compare and jump if not equal */
3933 /*-----------------------------------------------------------------*/
3935 gencjne (operand * left, operand * right, symbol * lbl)
3937 symbol *tlbl = newiTempLabel (NULL);
3939 gencjneshort (left, right, lbl);
3941 emitcode ("mov", "a,%s", one);
3942 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3943 emitcode ("", "%05d$:", lbl->key + 100);
3944 emitcode ("clr", "a");
3945 emitcode ("", "%05d$:", tlbl->key + 100);
3948 /*-----------------------------------------------------------------*/
3949 /* genCmpEq - generates code for equal to */
3950 /*-----------------------------------------------------------------*/
3952 genCmpEq (iCode * ic, iCode * ifx)
3954 operand *left, *right, *result;
3956 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3957 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3958 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3960 /* if literal, literal on the right or
3961 if the right is in a pointer register and left
3963 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3964 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3966 operand *t = IC_RIGHT (ic);
3967 IC_RIGHT (ic) = IC_LEFT (ic);
3971 if (ifx && !AOP_SIZE (result))
3974 /* if they are both bit variables */
3975 if (AOP_TYPE (left) == AOP_CRY &&
3976 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3978 if (AOP_TYPE (right) == AOP_LIT)
3980 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3983 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3984 emitcode ("cpl", "c");
3988 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3992 emitcode ("clr", "c");
3994 /* AOP_TYPE(right) == AOP_CRY */
3998 symbol *lbl = newiTempLabel (NULL);
3999 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4000 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4001 emitcode ("cpl", "c");
4002 emitcode ("", "%05d$:", (lbl->key + 100));
4004 /* if true label then we jump if condition
4006 tlbl = newiTempLabel (NULL);
4009 emitcode ("jnc", "%05d$", tlbl->key + 100);
4010 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4014 emitcode ("jc", "%05d$", tlbl->key + 100);
4015 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4017 emitcode ("", "%05d$:", tlbl->key + 100);
4021 tlbl = newiTempLabel (NULL);
4022 gencjneshort (left, right, tlbl);
4025 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4026 emitcode ("", "%05d$:", tlbl->key + 100);
4030 symbol *lbl = newiTempLabel (NULL);
4031 emitcode ("sjmp", "%05d$", lbl->key + 100);
4032 emitcode ("", "%05d$:", tlbl->key + 100);
4033 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4034 emitcode ("", "%05d$:", lbl->key + 100);
4037 /* mark the icode as generated */
4042 /* if they are both bit variables */
4043 if (AOP_TYPE (left) == AOP_CRY &&
4044 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4046 if (AOP_TYPE (right) == AOP_LIT)
4048 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4052 emitcode ("cpl", "c");
4056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4060 emitcode ("clr", "c");
4062 /* AOP_TYPE(right) == AOP_CRY */
4066 symbol *lbl = newiTempLabel (NULL);
4067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4068 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4069 emitcode ("cpl", "c");
4070 emitcode ("", "%05d$:", (lbl->key + 100));
4073 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4080 genIfxJump (ifx, "c");
4083 /* if the result is used in an arithmetic operation
4084 then put the result in place */
4089 gencjne (left, right, newiTempLabel (NULL));
4090 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4092 aopPut (AOP (result), "a", 0);
4097 genIfxJump (ifx, "a");
4100 /* if the result is used in an arithmetic operation
4101 then put the result in place */
4102 if (AOP_TYPE (result) != AOP_CRY)
4104 /* leave the result in acc */
4108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4110 freeAsmop (result, NULL, ic, TRUE);
4113 /*-----------------------------------------------------------------*/
4114 /* ifxForOp - returns the icode containing the ifx for operand */
4115 /*-----------------------------------------------------------------*/
4117 ifxForOp (operand * op, iCode * ic)
4119 /* if true symbol then needs to be assigned */
4120 if (IS_TRUE_SYMOP (op))
4123 /* if this has register type condition and
4124 the next instruction is ifx with the same operand
4125 and live to of the operand is upto the ifx only then */
4127 ic->next->op == IFX &&
4128 IC_COND (ic->next)->key == op->key &&
4129 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4135 /*-----------------------------------------------------------------*/
4136 /* hasInc - operand is incremented before any other use */
4137 /*-----------------------------------------------------------------*/
4139 hasInc (operand *op, iCode *ic)
4141 sym_link *type = operandType(op);
4142 sym_link *retype = getSpec (type);
4143 iCode *lic = ic->next;
4146 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4147 isize = getSize(type->next);
4149 /* if operand of the form op = op + <sizeof *op> */
4150 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4151 isOperandEqual(IC_RESULT(lic),op) &&
4152 isOperandLiteral(IC_RIGHT(lic)) &&
4153 operandLitValue(IC_RIGHT(lic)) == isize) {
4156 /* if the operand used or deffed */
4157 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4165 /*-----------------------------------------------------------------*/
4166 /* genAndOp - for && operation */
4167 /*-----------------------------------------------------------------*/
4169 genAndOp (iCode * ic)
4171 operand *left, *right, *result;
4174 /* note here that && operations that are in an
4175 if statement are taken away by backPatchLabels
4176 only those used in arthmetic operations remain */
4177 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4178 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4179 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4181 /* if both are bit variables */
4182 if (AOP_TYPE (left) == AOP_CRY &&
4183 AOP_TYPE (right) == AOP_CRY)
4185 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4186 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4191 tlbl = newiTempLabel (NULL);
4193 emitcode ("jz", "%05d$", tlbl->key + 100);
4195 emitcode ("", "%05d$:", tlbl->key + 100);
4199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4201 freeAsmop (result, NULL, ic, TRUE);
4205 /*-----------------------------------------------------------------*/
4206 /* genOrOp - for || operation */
4207 /*-----------------------------------------------------------------*/
4209 genOrOp (iCode * ic)
4211 operand *left, *right, *result;
4214 /* note here that || operations that are in an
4215 if statement are taken away by backPatchLabels
4216 only those used in arthmetic operations remain */
4217 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4218 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4219 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4221 /* if both are bit variables */
4222 if (AOP_TYPE (left) == AOP_CRY &&
4223 AOP_TYPE (right) == AOP_CRY)
4225 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4226 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4231 tlbl = newiTempLabel (NULL);
4233 emitcode ("jnz", "%05d$", tlbl->key + 100);
4235 emitcode ("", "%05d$:", tlbl->key + 100);
4239 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4240 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4241 freeAsmop (result, NULL, ic, TRUE);
4244 /*-----------------------------------------------------------------*/
4245 /* isLiteralBit - test if lit == 2^n */
4246 /*-----------------------------------------------------------------*/
4248 isLiteralBit (unsigned long lit)
4250 unsigned long pw[32] =
4251 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4252 0x100L, 0x200L, 0x400L, 0x800L,
4253 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4254 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4255 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4256 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4257 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4260 for (idx = 0; idx < 32; idx++)
4266 /*-----------------------------------------------------------------*/
4267 /* continueIfTrue - */
4268 /*-----------------------------------------------------------------*/
4270 continueIfTrue (iCode * ic)
4273 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4277 /*-----------------------------------------------------------------*/
4279 /*-----------------------------------------------------------------*/
4281 jumpIfTrue (iCode * ic)
4284 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4288 /*-----------------------------------------------------------------*/
4289 /* jmpTrueOrFalse - */
4290 /*-----------------------------------------------------------------*/
4292 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4294 // ugly but optimized by peephole
4297 symbol *nlbl = newiTempLabel (NULL);
4298 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4299 emitcode ("", "%05d$:", tlbl->key + 100);
4300 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4301 emitcode ("", "%05d$:", nlbl->key + 100);
4305 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4306 emitcode ("", "%05d$:", tlbl->key + 100);
4311 /*-----------------------------------------------------------------*/
4312 /* genAnd - code for and */
4313 /*-----------------------------------------------------------------*/
4315 genAnd (iCode * ic, iCode * ifx)
4317 operand *left, *right, *result;
4318 int size, offset = 0;
4319 unsigned long lit = 0L;
4323 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4324 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4325 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4328 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4330 AOP_TYPE (left), AOP_TYPE (right));
4331 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4333 AOP_SIZE (left), AOP_SIZE (right));
4336 /* if left is a literal & right is not then exchange them */
4337 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4338 AOP_NEEDSACC (left))
4340 operand *tmp = right;
4345 /* if result = right then exchange them */
4346 if (sameRegs (AOP (result), AOP (right)))
4348 operand *tmp = right;
4353 /* if right is bit then exchange them */
4354 if (AOP_TYPE (right) == AOP_CRY &&
4355 AOP_TYPE (left) != AOP_CRY)
4357 operand *tmp = right;
4361 if (AOP_TYPE (right) == AOP_LIT)
4362 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4364 size = AOP_SIZE (result);
4367 // result = bit & yy;
4368 if (AOP_TYPE (left) == AOP_CRY)
4370 // c = bit & literal;
4371 if (AOP_TYPE (right) == AOP_LIT)
4375 if (size && sameRegs (AOP (result), AOP (left)))
4378 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383 if (size && (AOP_TYPE (result) == AOP_CRY))
4385 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4388 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4393 emitcode ("clr", "c");
4398 if (AOP_TYPE (right) == AOP_CRY)
4401 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4402 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4407 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4409 emitcode ("rrc", "a");
4410 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4418 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4419 genIfxJump (ifx, "c");
4423 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4424 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4425 if ((AOP_TYPE (right) == AOP_LIT) &&
4426 (AOP_TYPE (result) == AOP_CRY) &&
4427 (AOP_TYPE (left) != AOP_CRY))
4429 int posbit = isLiteralBit (lit);
4434 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4437 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4443 sprintf (buffer, "acc.%d", posbit & 0x07);
4444 genIfxJump (ifx, buffer);
4451 symbol *tlbl = newiTempLabel (NULL);
4452 int sizel = AOP_SIZE (left);
4454 emitcode ("setb", "c");
4457 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4459 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4461 if ((posbit = isLiteralBit (bytelit)) != 0)
4462 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4465 if (bytelit != 0x0FFL)
4466 emitcode ("anl", "a,%s",
4467 aopGet (AOP (right), offset, FALSE, TRUE));
4468 emitcode ("jnz", "%05d$", tlbl->key + 100);
4473 // bit = left & literal
4476 emitcode ("clr", "c");
4477 emitcode ("", "%05d$:", tlbl->key + 100);
4479 // if(left & literal)
4483 jmpTrueOrFalse (ifx, tlbl);
4491 /* if left is same as result */
4492 if (sameRegs (AOP (result), AOP (left)))
4494 for (; size--; offset++)
4496 if (AOP_TYPE (right) == AOP_LIT)
4498 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4500 else if (bytelit == 0)
4501 aopPut (AOP (result), zero, offset);
4502 else if (IS_AOP_PREG (result))
4504 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4505 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4506 aopPut (AOP (result), "a", offset);
4509 emitcode ("anl", "%s,%s",
4510 aopGet (AOP (left), offset, FALSE, TRUE),
4511 aopGet (AOP (right), offset, FALSE, FALSE));
4515 if (AOP_TYPE (left) == AOP_ACC)
4516 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4519 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4520 if (IS_AOP_PREG (result))
4522 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4523 aopPut (AOP (result), "a", offset);
4527 emitcode ("anl", "%s,a",
4528 aopGet (AOP (left), offset, FALSE, TRUE));
4535 // left & result in different registers
4536 if (AOP_TYPE (result) == AOP_CRY)
4539 // if(size), result in bit
4540 // if(!size && ifx), conditional oper: if(left & right)
4541 symbol *tlbl = newiTempLabel (NULL);
4542 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4544 emitcode ("setb", "c");
4547 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4548 emitcode ("anl", "a,%s",
4549 aopGet (AOP (left), offset, FALSE, FALSE));
4550 emitcode ("jnz", "%05d$", tlbl->key + 100);
4556 emitcode ("", "%05d$:", tlbl->key + 100);
4560 jmpTrueOrFalse (ifx, tlbl);
4564 for (; (size--); offset++)
4567 // result = left & right
4568 if (AOP_TYPE (right) == AOP_LIT)
4570 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4572 aopPut (AOP (result),
4573 aopGet (AOP (left), offset, FALSE, FALSE),
4577 else if (bytelit == 0)
4579 aopPut (AOP (result), zero, offset);
4583 // faster than result <- left, anl result,right
4584 // and better if result is SFR
4585 if (AOP_TYPE (left) == AOP_ACC)
4586 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4589 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4590 emitcode ("anl", "a,%s",
4591 aopGet (AOP (left), offset, FALSE, FALSE));
4593 aopPut (AOP (result), "a", offset);
4599 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 freeAsmop (result, NULL, ic, TRUE);
4604 /*-----------------------------------------------------------------*/
4605 /* genOr - code for or */
4606 /*-----------------------------------------------------------------*/
4608 genOr (iCode * ic, iCode * ifx)
4610 operand *left, *right, *result;
4611 int size, offset = 0;
4612 unsigned long lit = 0L;
4614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4616 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4619 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4621 AOP_TYPE (left), AOP_TYPE (right));
4622 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4624 AOP_SIZE (left), AOP_SIZE (right));
4627 /* if left is a literal & right is not then exchange them */
4628 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4629 AOP_NEEDSACC (left))
4631 operand *tmp = right;
4636 /* if result = right then exchange them */
4637 if (sameRegs (AOP (result), AOP (right)))
4639 operand *tmp = right;
4644 /* if right is bit then exchange them */
4645 if (AOP_TYPE (right) == AOP_CRY &&
4646 AOP_TYPE (left) != AOP_CRY)
4648 operand *tmp = right;
4652 if (AOP_TYPE (right) == AOP_LIT)
4653 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4655 size = AOP_SIZE (result);
4659 if (AOP_TYPE (left) == AOP_CRY)
4661 if (AOP_TYPE (right) == AOP_LIT)
4663 // c = bit & literal;
4666 // lit != 0 => result = 1
4667 if (AOP_TYPE (result) == AOP_CRY)
4670 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4672 continueIfTrue (ifx);
4675 emitcode ("setb", "c");
4679 // lit == 0 => result = left
4680 if (size && sameRegs (AOP (result), AOP (left)))
4682 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4687 if (AOP_TYPE (right) == AOP_CRY)
4690 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4691 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4696 symbol *tlbl = newiTempLabel (NULL);
4697 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4698 emitcode ("setb", "c");
4699 emitcode ("jb", "%s,%05d$",
4700 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4702 emitcode ("jnz", "%05d$", tlbl->key + 100);
4703 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4705 jmpTrueOrFalse (ifx, tlbl);
4711 emitcode ("", "%05d$:", tlbl->key + 100);
4720 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4721 genIfxJump (ifx, "c");
4725 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4726 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4727 if ((AOP_TYPE (right) == AOP_LIT) &&
4728 (AOP_TYPE (result) == AOP_CRY) &&
4729 (AOP_TYPE (left) != AOP_CRY))
4735 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4737 continueIfTrue (ifx);
4742 // lit = 0, result = boolean(left)
4744 emitcode ("setb", "c");
4748 symbol *tlbl = newiTempLabel (NULL);
4749 emitcode ("jnz", "%05d$", tlbl->key + 100);
4751 emitcode ("", "%05d$:", tlbl->key + 100);
4755 genIfxJump (ifx, "a");
4763 /* if left is same as result */
4764 if (sameRegs (AOP (result), AOP (left)))
4766 for (; size--; offset++)
4768 if (AOP_TYPE (right) == AOP_LIT)
4770 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4772 else if (IS_AOP_PREG (left))
4774 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4775 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4776 aopPut (AOP (result), "a", offset);
4779 emitcode ("orl", "%s,%s",
4780 aopGet (AOP (left), offset, FALSE, TRUE),
4781 aopGet (AOP (right), offset, FALSE, FALSE));
4785 if (AOP_TYPE (left) == AOP_ACC)
4786 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4789 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4790 if (IS_AOP_PREG (left))
4792 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4793 aopPut (AOP (result), "a", offset);
4796 emitcode ("orl", "%s,a",
4797 aopGet (AOP (left), offset, FALSE, TRUE));
4804 // left & result in different registers
4805 if (AOP_TYPE (result) == AOP_CRY)
4808 // if(size), result in bit
4809 // if(!size && ifx), conditional oper: if(left | right)
4810 symbol *tlbl = newiTempLabel (NULL);
4811 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4813 emitcode ("setb", "c");
4816 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4817 emitcode ("orl", "a,%s",
4818 aopGet (AOP (left), offset, FALSE, FALSE));
4819 emitcode ("jnz", "%05d$", tlbl->key + 100);
4825 emitcode ("", "%05d$:", tlbl->key + 100);
4829 jmpTrueOrFalse (ifx, tlbl);
4832 for (; (size--); offset++)
4835 // result = left & right
4836 if (AOP_TYPE (right) == AOP_LIT)
4838 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4840 aopPut (AOP (result),
4841 aopGet (AOP (left), offset, FALSE, FALSE),
4846 // faster than result <- left, anl result,right
4847 // and better if result is SFR
4848 if (AOP_TYPE (left) == AOP_ACC)
4849 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4852 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4853 emitcode ("orl", "a,%s",
4854 aopGet (AOP (left), offset, FALSE, FALSE));
4856 aopPut (AOP (result), "a", offset);
4861 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4862 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (result, NULL, ic, TRUE);
4866 /*-----------------------------------------------------------------*/
4867 /* genXor - code for xclusive or */
4868 /*-----------------------------------------------------------------*/
4870 genXor (iCode * ic, iCode * ifx)
4872 operand *left, *right, *result;
4873 int size, offset = 0;
4874 unsigned long lit = 0L;
4876 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4877 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4878 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4881 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4883 AOP_TYPE (left), AOP_TYPE (right));
4884 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4886 AOP_SIZE (left), AOP_SIZE (right));
4889 /* if left is a literal & right is not ||
4890 if left needs acc & right does not */
4891 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4892 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4894 operand *tmp = right;
4899 /* if result = right then exchange them */
4900 if (sameRegs (AOP (result), AOP (right)))
4902 operand *tmp = right;
4907 /* if right is bit then exchange them */
4908 if (AOP_TYPE (right) == AOP_CRY &&
4909 AOP_TYPE (left) != AOP_CRY)
4911 operand *tmp = right;
4915 if (AOP_TYPE (right) == AOP_LIT)
4916 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4918 size = AOP_SIZE (result);
4922 if (AOP_TYPE (left) == AOP_CRY)
4924 if (AOP_TYPE (right) == AOP_LIT)
4926 // c = bit & literal;
4929 // lit>>1 != 0 => result = 1
4930 if (AOP_TYPE (result) == AOP_CRY)
4933 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4935 continueIfTrue (ifx);
4938 emitcode ("setb", "c");
4945 // lit == 0, result = left
4946 if (size && sameRegs (AOP (result), AOP (left)))
4948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4952 // lit == 1, result = not(left)
4953 if (size && sameRegs (AOP (result), AOP (left)))
4955 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4960 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4961 emitcode ("cpl", "c");
4970 symbol *tlbl = newiTempLabel (NULL);
4971 if (AOP_TYPE (right) == AOP_CRY)
4974 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4978 int sizer = AOP_SIZE (right);
4980 // if val>>1 != 0, result = 1
4981 emitcode ("setb", "c");
4984 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4986 // test the msb of the lsb
4987 emitcode ("anl", "a,#0xfe");
4988 emitcode ("jnz", "%05d$", tlbl->key + 100);
4992 emitcode ("rrc", "a");
4994 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4995 emitcode ("cpl", "c");
4996 emitcode ("", "%05d$:", (tlbl->key + 100));
5003 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5004 genIfxJump (ifx, "c");
5008 if (sameRegs (AOP (result), AOP (left)))
5010 /* if left is same as result */
5011 for (; size--; offset++)
5013 if (AOP_TYPE (right) == AOP_LIT)
5015 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5017 else if (IS_AOP_PREG (left))
5019 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5020 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5021 aopPut (AOP (result), "a", offset);
5024 emitcode ("xrl", "%s,%s",
5025 aopGet (AOP (left), offset, FALSE, TRUE),
5026 aopGet (AOP (right), offset, FALSE, FALSE));
5030 if (AOP_TYPE (left) == AOP_ACC)
5031 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5034 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5035 if (IS_AOP_PREG (left))
5037 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5038 aopPut (AOP (result), "a", offset);
5041 emitcode ("xrl", "%s,a",
5042 aopGet (AOP (left), offset, FALSE, TRUE));
5049 // left & result in different registers
5050 if (AOP_TYPE (result) == AOP_CRY)
5053 // if(size), result in bit
5054 // if(!size && ifx), conditional oper: if(left ^ right)
5055 symbol *tlbl = newiTempLabel (NULL);
5056 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5058 emitcode ("setb", "c");
5061 if ((AOP_TYPE (right) == AOP_LIT) &&
5062 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5064 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5068 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5069 emitcode ("xrl", "a,%s",
5070 aopGet (AOP (left), offset, FALSE, FALSE));
5072 emitcode ("jnz", "%05d$", tlbl->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5082 jmpTrueOrFalse (ifx, tlbl);
5085 for (; (size--); offset++)
5088 // result = left & right
5089 if (AOP_TYPE (right) == AOP_LIT)
5091 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5093 aopPut (AOP (result),
5094 aopGet (AOP (left), offset, FALSE, FALSE),
5099 // faster than result <- left, anl result,right
5100 // and better if result is SFR
5101 if (AOP_TYPE (left) == AOP_ACC)
5102 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5105 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5106 emitcode ("xrl", "a,%s",
5107 aopGet (AOP (left), offset, FALSE, TRUE));
5109 aopPut (AOP (result), "a", offset);
5114 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5116 freeAsmop (result, NULL, ic, TRUE);
5119 /*-----------------------------------------------------------------*/
5120 /* genInline - write the inline code out */
5121 /*-----------------------------------------------------------------*/
5123 genInline (iCode * ic)
5125 char *buffer, *bp, *bp1;
5127 _G.inLine += (!options.asmpeep);
5129 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5130 strcpy (buffer, IC_INLINE (ic));
5132 /* emit each line as a code */
5157 /* emitcode("",buffer); */
5158 _G.inLine -= (!options.asmpeep);
5161 /*-----------------------------------------------------------------*/
5162 /* genRRC - rotate right with carry */
5163 /*-----------------------------------------------------------------*/
5167 operand *left, *result;
5168 int size, offset = 0;
5171 /* rotate right with carry */
5172 left = IC_LEFT (ic);
5173 result = IC_RESULT (ic);
5174 aopOp (left, ic, FALSE);
5175 aopOp (result, ic, FALSE);
5177 /* move it to the result */
5178 size = AOP_SIZE (result);
5183 l = aopGet (AOP (left), offset, FALSE, FALSE);
5185 emitcode ("rrc", "a");
5186 if (AOP_SIZE (result) > 1)
5187 aopPut (AOP (result), "a", offset--);
5189 /* now we need to put the carry into the
5190 highest order byte of the result */
5191 if (AOP_SIZE (result) > 1)
5193 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5196 emitcode ("mov", "acc.7,c");
5197 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5198 freeAsmop (left, NULL, ic, TRUE);
5199 freeAsmop (result, NULL, ic, TRUE);
5202 /*-----------------------------------------------------------------*/
5203 /* genRLC - generate code for rotate left with carry */
5204 /*-----------------------------------------------------------------*/
5208 operand *left, *result;
5209 int size, offset = 0;
5212 /* rotate right with carry */
5213 left = IC_LEFT (ic);
5214 result = IC_RESULT (ic);
5215 aopOp (left, ic, FALSE);
5216 aopOp (result, ic, FALSE);
5218 /* move it to the result */
5219 size = AOP_SIZE (result);
5223 l = aopGet (AOP (left), offset, FALSE, FALSE);
5225 emitcode ("add", "a,acc");
5226 if (AOP_SIZE (result) > 1)
5227 aopPut (AOP (result), "a", offset++);
5230 l = aopGet (AOP (left), offset, FALSE, FALSE);
5232 emitcode ("rlc", "a");
5233 if (AOP_SIZE (result) > 1)
5234 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), 0, FALSE, FALSE);
5244 emitcode ("mov", "acc.0,c");
5245 aopPut (AOP (result), "a", 0);
5246 freeAsmop (left, NULL, ic, TRUE);
5247 freeAsmop (result, NULL, ic, TRUE);
5250 /*-----------------------------------------------------------------*/
5251 /* genGetHbit - generates code get highest order bit */
5252 /*-----------------------------------------------------------------*/
5254 genGetHbit (iCode * ic)
5256 operand *left, *result;
5257 left = IC_LEFT (ic);
5258 result = IC_RESULT (ic);
5259 aopOp (left, ic, FALSE);
5260 aopOp (result, ic, FALSE);
5262 /* get the highest order byte into a */
5263 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5264 if (AOP_TYPE (result) == AOP_CRY)
5266 emitcode ("rlc", "a");
5271 emitcode ("rl", "a");
5272 emitcode ("anl", "a,#0x01");
5277 freeAsmop (left, NULL, ic, TRUE);
5278 freeAsmop (result, NULL, ic, TRUE);
5281 /*-----------------------------------------------------------------*/
5282 /* AccRol - rotate left accumulator by known count */
5283 /*-----------------------------------------------------------------*/
5285 AccRol (int shCount)
5287 shCount &= 0x0007; // shCount : 0..7
5294 emitcode ("rl", "a");
5297 emitcode ("rl", "a");
5298 emitcode ("rl", "a");
5301 emitcode ("swap", "a");
5302 emitcode ("rr", "a");
5305 emitcode ("swap", "a");
5308 emitcode ("swap", "a");
5309 emitcode ("rl", "a");
5312 emitcode ("rr", "a");
5313 emitcode ("rr", "a");
5316 emitcode ("rr", "a");
5321 /*-----------------------------------------------------------------*/
5322 /* AccLsh - left shift accumulator by known count */
5323 /*-----------------------------------------------------------------*/
5325 AccLsh (int shCount)
5330 emitcode ("add", "a,acc");
5331 else if (shCount == 2)
5333 emitcode ("add", "a,acc");
5334 emitcode ("add", "a,acc");
5338 /* rotate left accumulator */
5340 /* and kill the lower order bits */
5341 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5346 /*-----------------------------------------------------------------*/
5347 /* AccRsh - right shift accumulator by known count */
5348 /*-----------------------------------------------------------------*/
5350 AccRsh (int shCount)
5357 emitcode ("rrc", "a");
5361 /* rotate right accumulator */
5362 AccRol (8 - shCount);
5363 /* and kill the higher order bits */
5364 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5369 /*-----------------------------------------------------------------*/
5370 /* AccSRsh - signed right shift accumulator by known count */
5371 /*-----------------------------------------------------------------*/
5373 AccSRsh (int shCount)
5380 emitcode ("mov", "c,acc.7");
5381 emitcode ("rrc", "a");
5383 else if (shCount == 2)
5385 emitcode ("mov", "c,acc.7");
5386 emitcode ("rrc", "a");
5387 emitcode ("mov", "c,acc.7");
5388 emitcode ("rrc", "a");
5392 tlbl = newiTempLabel (NULL);
5393 /* rotate right accumulator */
5394 AccRol (8 - shCount);
5395 /* and kill the higher order bits */
5396 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5397 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5398 emitcode ("orl", "a,#0x%02x",
5399 (unsigned char) ~SRMask[shCount]);
5400 emitcode ("", "%05d$:", tlbl->key + 100);
5405 /*-----------------------------------------------------------------*/
5406 /* shiftR1Left2Result - shift right one byte from left to result */
5407 /*-----------------------------------------------------------------*/
5409 shiftR1Left2Result (operand * left, int offl,
5410 operand * result, int offr,
5411 int shCount, int sign)
5413 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5414 /* shift right accumulator */
5419 aopPut (AOP (result), "a", offr);
5422 /*-----------------------------------------------------------------*/
5423 /* shiftL1Left2Result - shift left one byte from left to result */
5424 /*-----------------------------------------------------------------*/
5426 shiftL1Left2Result (operand * left, int offl,
5427 operand * result, int offr, int shCount)
5430 l = aopGet (AOP (left), offl, FALSE, FALSE);
5432 /* shift left accumulator */
5434 aopPut (AOP (result), "a", offr);
5437 /*-----------------------------------------------------------------*/
5438 /* movLeft2Result - move byte from left to result */
5439 /*-----------------------------------------------------------------*/
5441 movLeft2Result (operand * left, int offl,
5442 operand * result, int offr, int sign)
5445 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5447 l = aopGet (AOP (left), offl, FALSE, FALSE);
5449 if (*l == '@' && (IS_AOP_PREG (result)))
5451 emitcode ("mov", "a,%s", l);
5452 aopPut (AOP (result), "a", offr);
5457 aopPut (AOP (result), l, offr);
5460 /* MSB sign in acc.7 ! */
5461 if (getDataSize (left) == offl + 1)
5463 emitcode ("mov", "a,%s", l);
5464 aopPut (AOP (result), "a", offr);
5471 /*-----------------------------------------------------------------*/
5472 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5473 /*-----------------------------------------------------------------*/
5477 emitcode ("rrc", "a");
5478 emitcode ("xch", "a,%s", x);
5479 emitcode ("rrc", "a");
5480 emitcode ("xch", "a,%s", x);
5483 /*-----------------------------------------------------------------*/
5484 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5485 /*-----------------------------------------------------------------*/
5489 emitcode ("xch", "a,%s", x);
5490 emitcode ("rlc", "a");
5491 emitcode ("xch", "a,%s", x);
5492 emitcode ("rlc", "a");
5495 /*-----------------------------------------------------------------*/
5496 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5497 /*-----------------------------------------------------------------*/
5501 emitcode ("xch", "a,%s", x);
5502 emitcode ("add", "a,acc");
5503 emitcode ("xch", "a,%s", x);
5504 emitcode ("rlc", "a");
5507 /*-----------------------------------------------------------------*/
5508 /* AccAXLsh - left shift a:x by known count (0..7) */
5509 /*-----------------------------------------------------------------*/
5511 AccAXLsh (char *x, int shCount)
5526 case 5: // AAAAABBB:CCCCCDDD
5528 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5530 emitcode ("anl", "a,#0x%02x",
5531 SLMask[shCount]); // BBB00000:CCCCCDDD
5533 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5535 AccRol (shCount); // DDDCCCCC:BBB00000
5537 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5539 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5541 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5543 emitcode ("anl", "a,#0x%02x",
5544 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5546 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5548 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5551 case 6: // AAAAAABB:CCCCCCDD
5552 emitcode ("anl", "a,#0x%02x",
5553 SRMask[shCount]); // 000000BB:CCCCCCDD
5554 emitcode ("mov", "c,acc.0"); // c = B
5555 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5557 AccAXRrl1 (x); // BCCCCCCD:D000000B
5558 AccAXRrl1 (x); // BBCCCCCC:DD000000
5560 emitcode("rrc","a");
5561 emitcode("xch","a,%s", x);
5562 emitcode("rrc","a");
5563 emitcode("mov","c,acc.0"); //<< get correct bit
5564 emitcode("xch","a,%s", x);
5566 emitcode("rrc","a");
5567 emitcode("xch","a,%s", x);
5568 emitcode("rrc","a");
5569 emitcode("xch","a,%s", x);
5572 case 7: // a:x <<= 7
5574 emitcode ("anl", "a,#0x%02x",
5575 SRMask[shCount]); // 0000000B:CCCCCCCD
5577 emitcode ("mov", "c,acc.0"); // c = B
5579 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5581 AccAXRrl1 (x); // BCCCCCCC:D0000000
5589 /*-----------------------------------------------------------------*/
5590 /* AccAXRsh - right shift a:x known count (0..7) */
5591 /*-----------------------------------------------------------------*/
5593 AccAXRsh (char *x, int shCount)
5601 AccAXRrl1 (x); // 0->a:x
5606 AccAXRrl1 (x); // 0->a:x
5609 AccAXRrl1 (x); // 0->a:x
5614 case 5: // AAAAABBB:CCCCCDDD = a:x
5616 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5618 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5620 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5622 emitcode ("anl", "a,#0x%02x",
5623 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5625 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5627 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5629 emitcode ("anl", "a,#0x%02x",
5630 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5632 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5634 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5636 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5639 case 6: // AABBBBBB:CCDDDDDD
5641 emitcode ("mov", "c,acc.7");
5642 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5644 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5646 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5648 emitcode ("anl", "a,#0x%02x",
5649 SRMask[shCount]); // 000000AA:BBBBBBCC
5652 case 7: // ABBBBBBB:CDDDDDDD
5654 emitcode ("mov", "c,acc.7"); // c = A
5656 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5658 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5660 emitcode ("anl", "a,#0x%02x",
5661 SRMask[shCount]); // 0000000A:BBBBBBBC
5669 /*-----------------------------------------------------------------*/
5670 /* AccAXRshS - right shift signed a:x known count (0..7) */
5671 /*-----------------------------------------------------------------*/
5673 AccAXRshS (char *x, int shCount)
5681 emitcode ("mov", "c,acc.7");
5682 AccAXRrl1 (x); // s->a:x
5686 emitcode ("mov", "c,acc.7");
5687 AccAXRrl1 (x); // s->a:x
5689 emitcode ("mov", "c,acc.7");
5690 AccAXRrl1 (x); // s->a:x
5695 case 5: // AAAAABBB:CCCCCDDD = a:x
5697 tlbl = newiTempLabel (NULL);
5698 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5700 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5702 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5704 emitcode ("anl", "a,#0x%02x",
5705 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5707 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5709 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5711 emitcode ("anl", "a,#0x%02x",
5712 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5714 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5716 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5718 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5720 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5721 emitcode ("orl", "a,#0x%02x",
5722 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5724 emitcode ("", "%05d$:", tlbl->key + 100);
5725 break; // SSSSAAAA:BBBCCCCC
5727 case 6: // AABBBBBB:CCDDDDDD
5729 tlbl = newiTempLabel (NULL);
5730 emitcode ("mov", "c,acc.7");
5731 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5733 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5735 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5737 emitcode ("anl", "a,#0x%02x",
5738 SRMask[shCount]); // 000000AA:BBBBBBCC
5740 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5741 emitcode ("orl", "a,#0x%02x",
5742 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5744 emitcode ("", "%05d$:", tlbl->key + 100);
5746 case 7: // ABBBBBBB:CDDDDDDD
5748 tlbl = newiTempLabel (NULL);
5749 emitcode ("mov", "c,acc.7"); // c = A
5751 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5753 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5755 emitcode ("anl", "a,#0x%02x",
5756 SRMask[shCount]); // 0000000A:BBBBBBBC
5758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5759 emitcode ("orl", "a,#0x%02x",
5760 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5762 emitcode ("", "%05d$:", tlbl->key + 100);
5769 /*-----------------------------------------------------------------*/
5770 /* shiftL2Left2Result - shift left two bytes from left to result */
5771 /*-----------------------------------------------------------------*/
5773 shiftL2Left2Result (operand * left, int offl,
5774 operand * result, int offr, int shCount)
5776 if (sameRegs (AOP (result), AOP (left)) &&
5777 ((offl + MSB16) == offr))
5779 /* don't crash result[offr] */
5780 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5781 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5785 movLeft2Result (left, offl, result, offr, 0);
5786 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5788 /* ax << shCount (x = lsb(result)) */
5789 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5790 aopPut (AOP (result), "a", offr + MSB16);
5794 /*-----------------------------------------------------------------*/
5795 /* shiftR2Left2Result - shift right two bytes from left to result */
5796 /*-----------------------------------------------------------------*/
5798 shiftR2Left2Result (operand * left, int offl,
5799 operand * result, int offr,
5800 int shCount, int sign)
5802 if (sameRegs (AOP (result), AOP (left)) &&
5803 ((offl + MSB16) == offr))
5805 /* don't crash result[offr] */
5806 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5807 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5811 movLeft2Result (left, offl, result, offr, 0);
5812 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5814 /* a:x >> shCount (x = lsb(result)) */
5816 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5818 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5819 if (getDataSize (result) > 1)
5820 aopPut (AOP (result), "a", offr + MSB16);
5823 /*-----------------------------------------------------------------*/
5824 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5825 /*-----------------------------------------------------------------*/
5827 shiftLLeftOrResult (operand * left, int offl,
5828 operand * result, int offr, int shCount)
5830 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5831 /* shift left accumulator */
5833 /* or with result */
5834 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5835 /* back to result */
5836 aopPut (AOP (result), "a", offr);
5839 /*-----------------------------------------------------------------*/
5840 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5841 /*-----------------------------------------------------------------*/
5843 shiftRLeftOrResult (operand * left, int offl,
5844 operand * result, int offr, int shCount)
5846 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5847 /* shift right accumulator */
5849 /* or with result */
5850 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5851 /* back to result */
5852 aopPut (AOP (result), "a", offr);
5855 /*-----------------------------------------------------------------*/
5856 /* genlshOne - left shift a one byte quantity by known count */
5857 /*-----------------------------------------------------------------*/
5859 genlshOne (operand * result, operand * left, int shCount)
5861 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5864 /*-----------------------------------------------------------------*/
5865 /* genlshTwo - left shift two bytes by known amount != 0 */
5866 /*-----------------------------------------------------------------*/
5868 genlshTwo (operand * result, operand * left, int shCount)
5872 size = getDataSize (result);
5874 /* if shCount >= 8 */
5882 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5884 movLeft2Result (left, LSB, result, MSB16, 0);
5886 aopPut (AOP (result), zero, LSB);
5889 /* 1 <= shCount <= 7 */
5893 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5895 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5899 /*-----------------------------------------------------------------*/
5900 /* shiftLLong - shift left one long from left to result */
5901 /* offl = LSB or MSB16 */
5902 /*-----------------------------------------------------------------*/
5904 shiftLLong (operand * left, operand * result, int offr)
5907 int size = AOP_SIZE (result);
5909 if (size >= LSB + offr)
5911 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5913 emitcode ("add", "a,acc");
5914 if (sameRegs (AOP (left), AOP (result)) &&
5915 size >= MSB16 + offr && offr != LSB)
5916 emitcode ("xch", "a,%s",
5917 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5919 aopPut (AOP (result), "a", LSB + offr);
5922 if (size >= MSB16 + offr)
5924 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5926 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5929 emitcode ("rlc", "a");
5930 if (sameRegs (AOP (left), AOP (result)) &&
5931 size >= MSB24 + offr && offr != LSB)
5932 emitcode ("xch", "a,%s",
5933 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5935 aopPut (AOP (result), "a", MSB16 + offr);
5938 if (size >= MSB24 + offr)
5940 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5942 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5945 emitcode ("rlc", "a");
5946 if (sameRegs (AOP (left), AOP (result)) &&
5947 size >= MSB32 + offr && offr != LSB)
5948 emitcode ("xch", "a,%s",
5949 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5951 aopPut (AOP (result), "a", MSB24 + offr);
5954 if (size > MSB32 + offr)
5956 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5958 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5961 emitcode ("rlc", "a");
5962 aopPut (AOP (result), "a", MSB32 + offr);
5965 aopPut (AOP (result), zero, LSB);
5968 /*-----------------------------------------------------------------*/
5969 /* genlshFour - shift four byte by a known amount != 0 */
5970 /*-----------------------------------------------------------------*/
5972 genlshFour (operand * result, operand * left, int shCount)
5976 size = AOP_SIZE (result);
5978 /* if shifting more that 3 bytes */
5983 /* lowest order of left goes to the highest
5984 order of the destination */
5985 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5987 movLeft2Result (left, LSB, result, MSB32, 0);
5988 aopPut (AOP (result), zero, LSB);
5989 aopPut (AOP (result), zero, MSB16);
5990 aopPut (AOP (result), zero, MSB24);
5994 /* more than two bytes */
5995 else if (shCount >= 16)
5997 /* lower order two bytes goes to higher order two bytes */
5999 /* if some more remaining */
6001 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6004 movLeft2Result (left, MSB16, result, MSB32, 0);
6005 movLeft2Result (left, LSB, result, MSB24, 0);
6007 aopPut (AOP (result), zero, MSB16);
6008 aopPut (AOP (result), zero, LSB);
6012 /* if more than 1 byte */
6013 else if (shCount >= 8)
6015 /* lower order three bytes goes to higher order three bytes */
6020 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6022 movLeft2Result (left, LSB, result, MSB16, 0);
6028 movLeft2Result (left, MSB24, result, MSB32, 0);
6029 movLeft2Result (left, MSB16, result, MSB24, 0);
6030 movLeft2Result (left, LSB, result, MSB16, 0);
6031 aopPut (AOP (result), zero, LSB);
6033 else if (shCount == 1)
6034 shiftLLong (left, result, MSB16);
6037 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6038 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6039 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6040 aopPut (AOP (result), zero, LSB);
6045 /* 1 <= shCount <= 7 */
6046 else if (shCount <= 2)
6048 shiftLLong (left, result, LSB);
6050 shiftLLong (result, result, LSB);
6052 /* 3 <= shCount <= 7, optimize */
6055 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6056 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6057 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6061 /*-----------------------------------------------------------------*/
6062 /* genLeftShiftLiteral - left shifting by known count */
6063 /*-----------------------------------------------------------------*/
6065 genLeftShiftLiteral (operand * left,
6070 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6073 freeAsmop (right, NULL, ic, TRUE);
6075 aopOp (left, ic, FALSE);
6076 aopOp (result, ic, FALSE);
6078 size = getSize (operandType (result));
6081 emitcode ("; shift left ", "result %d, left %d", size,
6085 /* I suppose that the left size >= result size */
6090 movLeft2Result (left, size, result, size, 0);
6094 else if (shCount >= (size * 8))
6096 aopPut (AOP (result), zero, size);
6102 genlshOne (result, left, shCount);
6107 genlshTwo (result, left, shCount);
6111 genlshFour (result, left, shCount);
6115 freeAsmop (left, NULL, ic, TRUE);
6116 freeAsmop (result, NULL, ic, TRUE);
6119 /*-----------------------------------------------------------------*/
6120 /* genLeftShift - generates code for left shifting */
6121 /*-----------------------------------------------------------------*/
6123 genLeftShift (iCode * ic)
6125 operand *left, *right, *result;
6128 symbol *tlbl, *tlbl1;
6130 right = IC_RIGHT (ic);
6131 left = IC_LEFT (ic);
6132 result = IC_RESULT (ic);
6134 aopOp (right, ic, FALSE);
6136 /* if the shift count is known then do it
6137 as efficiently as possible */
6138 if (AOP_TYPE (right) == AOP_LIT)
6140 genLeftShiftLiteral (left, right, result, ic);
6144 /* shift count is unknown then we have to form
6145 a loop get the loop count in B : Note: we take
6146 only the lower order byte since shifting
6147 more that 32 bits make no sense anyway, ( the
6148 largest size of an object can be only 32 bits ) */
6150 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6151 emitcode ("inc", "b");
6152 freeAsmop (right, NULL, ic, TRUE);
6153 aopOp (left, ic, FALSE);
6154 aopOp (result, ic, FALSE);
6156 /* now move the left to the result if they are not the
6158 if (!sameRegs (AOP (left), AOP (result)) &&
6159 AOP_SIZE (result) > 1)
6162 size = AOP_SIZE (result);
6166 l = aopGet (AOP (left), offset, FALSE, TRUE);
6167 if (*l == '@' && (IS_AOP_PREG (result)))
6170 emitcode ("mov", "a,%s", l);
6171 aopPut (AOP (result), "a", offset);
6174 aopPut (AOP (result), l, offset);
6179 tlbl = newiTempLabel (NULL);
6180 size = AOP_SIZE (result);
6182 tlbl1 = newiTempLabel (NULL);
6184 /* if it is only one byte then */
6187 symbol *tlbl1 = newiTempLabel (NULL);
6189 l = aopGet (AOP (left), 0, FALSE, FALSE);
6191 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6192 emitcode ("", "%05d$:", tlbl->key + 100);
6193 emitcode ("add", "a,acc");
6194 emitcode ("", "%05d$:", tlbl1->key + 100);
6195 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6196 aopPut (AOP (result), "a", 0);
6200 reAdjustPreg (AOP (result));
6202 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6203 emitcode ("", "%05d$:", tlbl->key + 100);
6204 l = aopGet (AOP (result), offset, FALSE, FALSE);
6206 emitcode ("add", "a,acc");
6207 aopPut (AOP (result), "a", offset++);
6210 l = aopGet (AOP (result), offset, FALSE, FALSE);
6212 emitcode ("rlc", "a");
6213 aopPut (AOP (result), "a", offset++);
6215 reAdjustPreg (AOP (result));
6217 emitcode ("", "%05d$:", tlbl1->key + 100);
6218 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6220 freeAsmop (left, NULL, ic, TRUE);
6221 freeAsmop (result, NULL, ic, TRUE);
6224 /*-----------------------------------------------------------------*/
6225 /* genrshOne - right shift a one byte quantity by known count */
6226 /*-----------------------------------------------------------------*/
6228 genrshOne (operand * result, operand * left,
6229 int shCount, int sign)
6231 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6234 /*-----------------------------------------------------------------*/
6235 /* genrshTwo - right shift two bytes by known amount != 0 */
6236 /*-----------------------------------------------------------------*/
6238 genrshTwo (operand * result, operand * left,
6239 int shCount, int sign)
6241 /* if shCount >= 8 */
6246 shiftR1Left2Result (left, MSB16, result, LSB,
6249 movLeft2Result (left, MSB16, result, LSB, sign);
6250 addSign (result, MSB16, sign);
6253 /* 1 <= shCount <= 7 */
6255 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6258 /*-----------------------------------------------------------------*/
6259 /* shiftRLong - shift right one long from left to result */
6260 /* offl = LSB or MSB16 */
6261 /*-----------------------------------------------------------------*/
6263 shiftRLong (operand * left, int offl,
6264 operand * result, int sign)
6267 emitcode ("clr", "c");
6268 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6270 emitcode ("mov", "c,acc.7");
6271 emitcode ("rrc", "a");
6272 aopPut (AOP (result), "a", MSB32 - offl);
6274 /* add sign of "a" */
6275 addSign (result, MSB32, sign);
6277 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6278 emitcode ("rrc", "a");
6279 aopPut (AOP (result), "a", MSB24 - offl);
6281 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6282 emitcode ("rrc", "a");
6283 aopPut (AOP (result), "a", MSB16 - offl);
6287 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6288 emitcode ("rrc", "a");
6289 aopPut (AOP (result), "a", LSB);
6293 /*-----------------------------------------------------------------*/
6294 /* genrshFour - shift four byte by a known amount != 0 */
6295 /*-----------------------------------------------------------------*/
6297 genrshFour (operand * result, operand * left,
6298 int shCount, int sign)
6300 /* if shifting more that 3 bytes */
6305 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6307 movLeft2Result (left, MSB32, result, LSB, sign);
6308 addSign (result, MSB16, sign);
6310 else if (shCount >= 16)
6314 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6317 movLeft2Result (left, MSB24, result, LSB, 0);
6318 movLeft2Result (left, MSB32, result, MSB16, sign);
6320 addSign (result, MSB24, sign);
6322 else if (shCount >= 8)
6326 shiftRLong (left, MSB16, result, sign);
6327 else if (shCount == 0)
6329 movLeft2Result (left, MSB16, result, LSB, 0);
6330 movLeft2Result (left, MSB24, result, MSB16, 0);
6331 movLeft2Result (left, MSB32, result, MSB24, sign);
6332 addSign (result, MSB32, sign);
6336 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6337 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6338 /* the last shift is signed */
6339 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6340 addSign (result, MSB32, sign);
6344 { /* 1 <= shCount <= 7 */
6347 shiftRLong (left, LSB, result, sign);
6349 shiftRLong (result, LSB, result, sign);
6353 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6354 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6355 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6360 /*-----------------------------------------------------------------*/
6361 /* genRightShiftLiteral - right shifting by known count */
6362 /*-----------------------------------------------------------------*/
6364 genRightShiftLiteral (operand * left,
6370 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6373 freeAsmop (right, NULL, ic, TRUE);
6375 aopOp (left, ic, FALSE);
6376 aopOp (result, ic, FALSE);
6379 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6383 size = getDataSize (left);
6384 /* test the LEFT size !!! */
6386 /* I suppose that the left size >= result size */
6389 size = getDataSize (result);
6391 movLeft2Result (left, size, result, size, 0);
6394 else if (shCount >= (size * 8))
6397 /* get sign in acc.7 */
6398 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6399 addSign (result, LSB, sign);
6406 genrshOne (result, left, shCount, sign);
6410 genrshTwo (result, left, shCount, sign);
6414 genrshFour (result, left, shCount, sign);
6420 freeAsmop (left, NULL, ic, TRUE);
6421 freeAsmop (result, NULL, ic, TRUE);
6425 /*-----------------------------------------------------------------*/
6426 /* genSignedRightShift - right shift of signed number */
6427 /*-----------------------------------------------------------------*/
6429 genSignedRightShift (iCode * ic)
6431 operand *right, *left, *result;
6434 symbol *tlbl, *tlbl1;
6436 /* we do it the hard way put the shift count in b
6437 and loop thru preserving the sign */
6439 right = IC_RIGHT (ic);
6440 left = IC_LEFT (ic);
6441 result = IC_RESULT (ic);
6443 aopOp (right, ic, FALSE);
6446 if (AOP_TYPE (right) == AOP_LIT)
6448 genRightShiftLiteral (left, right, result, ic, 1);
6451 /* shift count is unknown then we have to form
6452 a loop get the loop count in B : Note: we take
6453 only the lower order byte since shifting
6454 more that 32 bits make no sense anyway, ( the
6455 largest size of an object can be only 32 bits ) */
6457 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6458 emitcode ("inc", "b");
6459 freeAsmop (right, NULL, ic, TRUE);
6460 aopOp (left, ic, FALSE);
6461 aopOp (result, ic, FALSE);
6463 /* now move the left to the result if they are not the
6465 if (!sameRegs (AOP (left), AOP (result)) &&
6466 AOP_SIZE (result) > 1)
6469 size = AOP_SIZE (result);
6473 l = aopGet (AOP (left), offset, FALSE, TRUE);
6474 if (*l == '@' && IS_AOP_PREG (result))
6477 emitcode ("mov", "a,%s", l);
6478 aopPut (AOP (result), "a", offset);
6481 aopPut (AOP (result), l, offset);
6486 /* mov the highest order bit to OVR */
6487 tlbl = newiTempLabel (NULL);
6488 tlbl1 = newiTempLabel (NULL);
6490 size = AOP_SIZE (result);
6492 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6493 emitcode ("rlc", "a");
6494 emitcode ("mov", "ov,c");
6495 /* if it is only one byte then */
6498 l = aopGet (AOP (left), 0, FALSE, FALSE);
6500 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6501 emitcode ("", "%05d$:", tlbl->key + 100);
6502 emitcode ("mov", "c,ov");
6503 emitcode ("rrc", "a");
6504 emitcode ("", "%05d$:", tlbl1->key + 100);
6505 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6506 aopPut (AOP (result), "a", 0);
6510 reAdjustPreg (AOP (result));
6511 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6512 emitcode ("", "%05d$:", tlbl->key + 100);
6513 emitcode ("mov", "c,ov");
6516 l = aopGet (AOP (result), offset, FALSE, FALSE);
6518 emitcode ("rrc", "a");
6519 aopPut (AOP (result), "a", offset--);
6521 reAdjustPreg (AOP (result));
6522 emitcode ("", "%05d$:", tlbl1->key + 100);
6523 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6526 freeAsmop (left, NULL, ic, TRUE);
6527 freeAsmop (result, NULL, ic, TRUE);
6530 /*-----------------------------------------------------------------*/
6531 /* genRightShift - generate code for right shifting */
6532 /*-----------------------------------------------------------------*/
6534 genRightShift (iCode * ic)
6536 operand *right, *left, *result;
6540 symbol *tlbl, *tlbl1;
6542 /* if signed then we do it the hard way preserve the
6543 sign bit moving it inwards */
6544 retype = getSpec (operandType (IC_RESULT (ic)));
6546 if (!SPEC_USIGN (retype))
6548 genSignedRightShift (ic);
6552 /* signed & unsigned types are treated the same : i.e. the
6553 signed is NOT propagated inwards : quoting from the
6554 ANSI - standard : "for E1 >> E2, is equivalent to division
6555 by 2**E2 if unsigned or if it has a non-negative value,
6556 otherwise the result is implementation defined ", MY definition
6557 is that the sign does not get propagated */
6559 right = IC_RIGHT (ic);
6560 left = IC_LEFT (ic);
6561 result = IC_RESULT (ic);
6563 aopOp (right, ic, FALSE);
6565 /* if the shift count is known then do it
6566 as efficiently as possible */
6567 if (AOP_TYPE (right) == AOP_LIT)
6569 genRightShiftLiteral (left, right, result, ic, 0);
6573 /* shift count is unknown then we have to form
6574 a loop get the loop count in B : Note: we take
6575 only the lower order byte since shifting
6576 more that 32 bits make no sense anyway, ( the
6577 largest size of an object can be only 32 bits ) */
6579 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6580 emitcode ("inc", "b");
6581 freeAsmop (right, NULL, ic, TRUE);
6582 aopOp (left, ic, FALSE);
6583 aopOp (result, ic, FALSE);
6585 /* now move the left to the result if they are not the
6587 if (!sameRegs (AOP (left), AOP (result)) &&
6588 AOP_SIZE (result) > 1)
6591 size = AOP_SIZE (result);
6595 l = aopGet (AOP (left), offset, FALSE, TRUE);
6596 if (*l == '@' && IS_AOP_PREG (result))
6599 emitcode ("mov", "a,%s", l);
6600 aopPut (AOP (result), "a", offset);
6603 aopPut (AOP (result), l, offset);
6608 tlbl = newiTempLabel (NULL);
6609 tlbl1 = newiTempLabel (NULL);
6610 size = AOP_SIZE (result);
6613 /* if it is only one byte then */
6616 l = aopGet (AOP (left), 0, FALSE, FALSE);
6618 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6619 emitcode ("", "%05d$:", tlbl->key + 100);
6621 emitcode ("rrc", "a");
6622 emitcode ("", "%05d$:", tlbl1->key + 100);
6623 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6624 aopPut (AOP (result), "a", 0);
6628 reAdjustPreg (AOP (result));
6629 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6630 emitcode ("", "%05d$:", tlbl->key + 100);
6634 l = aopGet (AOP (result), offset, FALSE, FALSE);
6636 emitcode ("rrc", "a");
6637 aopPut (AOP (result), "a", offset--);
6639 reAdjustPreg (AOP (result));
6641 emitcode ("", "%05d$:", tlbl1->key + 100);
6642 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6645 freeAsmop (left, NULL, ic, TRUE);
6646 freeAsmop (result, NULL, ic, TRUE);
6649 /*-----------------------------------------------------------------*/
6650 /* genUnpackBits - generates code for unpacking bits */
6651 /*-----------------------------------------------------------------*/
6653 genUnpackBits (operand * result, char *rname, int ptype)
6661 etype = getSpec (operandType (result));
6662 rsize = getSize (operandType (result));
6663 /* read the first byte */
6669 emitcode ("mov", "a,@%s", rname);
6673 emitcode ("movx", "a,@%s", rname);
6677 emitcode ("movx", "a,@dptr");
6681 emitcode ("clr", "a");
6682 emitcode ("movc", "a,%s", "@a+dptr");
6686 emitcode ("lcall", "__gptrget");
6690 rlen = SPEC_BLEN (etype);
6692 /* if we have bitdisplacement then it fits */
6693 /* into this byte completely or if length is */
6694 /* less than a byte */
6695 if ((shCnt = SPEC_BSTR (etype)) ||
6696 (SPEC_BLEN (etype) <= 8))
6699 /* shift right acc */
6702 emitcode ("anl", "a,#0x%02x",
6703 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6704 aopPut (AOP (result), "a", offset++);
6708 /* bit field did not fit in a byte */
6709 aopPut (AOP (result), "a", offset++);
6718 emitcode ("inc", "%s", rname);
6719 emitcode ("mov", "a,@%s", rname);
6723 emitcode ("inc", "%s", rname);
6724 emitcode ("movx", "a,@%s", rname);
6728 emitcode ("inc", "dptr");
6729 emitcode ("movx", "a,@dptr");
6733 emitcode ("clr", "a");
6734 emitcode ("inc", "dptr");
6735 emitcode ("movc", "a", "@a+dptr");
6739 emitcode ("inc", "dptr");
6740 emitcode ("lcall", "__gptrget");
6745 /* if we are done */
6749 aopPut (AOP (result), "a", offset++);
6755 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6757 aopPut (AOP (result), "a", offset++);
6765 aopPut (AOP (result), zero, offset++);
6771 /*-----------------------------------------------------------------*/
6772 /* genDataPointerGet - generates code when ptr offset is known */
6773 /*-----------------------------------------------------------------*/
6775 genDataPointerGet (operand * left,
6781 int size, offset = 0;
6782 aopOp (result, ic, TRUE);
6784 /* get the string representation of the name */
6785 l = aopGet (AOP (left), 0, FALSE, TRUE);
6786 size = AOP_SIZE (result);
6790 sprintf (buffer, "(%s + %d)", l + 1, offset);
6792 sprintf (buffer, "%s", l + 1);
6793 aopPut (AOP (result), buffer, offset++);
6796 freeAsmop (left, NULL, ic, TRUE);
6797 freeAsmop (result, NULL, ic, TRUE);
6800 /*-----------------------------------------------------------------*/
6801 /* genNearPointerGet - emitcode for near pointer fetch */
6802 /*-----------------------------------------------------------------*/
6804 genNearPointerGet (operand * left,
6812 sym_link *rtype, *retype;
6813 sym_link *ltype = operandType (left);
6816 rtype = operandType (result);
6817 retype = getSpec (rtype);
6819 aopOp (left, ic, FALSE);
6821 /* if left is rematerialisable and
6822 result is not bit variable type and
6823 the left is pointer to data space i.e
6824 lower 128 bytes of space */
6825 if (AOP_TYPE (left) == AOP_IMMD &&
6826 !IS_BITVAR (retype) &&
6827 DCL_TYPE (ltype) == POINTER)
6829 genDataPointerGet (left, result, ic);
6833 /* if the value is already in a pointer register
6834 then don't need anything more */
6835 if (!AOP_INPREG (AOP (left)))
6837 /* otherwise get a free pointer register */
6839 preg = getFreePtr (ic, &aop, FALSE);
6840 emitcode ("mov", "%s,%s",
6842 aopGet (AOP (left), 0, FALSE, TRUE));
6846 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6848 aopOp (result, ic, FALSE);
6850 /* if bitfield then unpack the bits */
6851 if (IS_BITVAR (retype))
6852 genUnpackBits (result, rname, POINTER);
6855 /* we have can just get the values */
6856 int size = AOP_SIZE (result);
6861 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6864 emitcode ("mov", "a,@%s", rname);
6865 aopPut (AOP (result), "a", offset);
6869 sprintf (buffer, "@%s", rname);
6870 aopPut (AOP (result), buffer, offset);
6874 emitcode ("inc", "%s", rname);
6878 /* now some housekeeping stuff */
6879 if (aop) /* we had to allocate for this iCode */
6881 if (pi) { /* post increment present */
6882 aopPut(AOP ( left ),rname,0);
6884 freeAsmop (NULL, aop, ic, TRUE);
6888 /* we did not allocate which means left
6889 already in a pointer register, then
6890 if size > 0 && this could be used again
6891 we have to point it back to where it
6893 if ((AOP_SIZE (result) > 1 &&
6894 !OP_SYMBOL (left)->remat &&
6895 (OP_SYMBOL (left)->liveTo > ic->seq ||
6899 int size = AOP_SIZE (result) - 1;
6901 emitcode ("dec", "%s", rname);
6906 freeAsmop (left, NULL, ic, TRUE);
6907 freeAsmop (result, NULL, ic, TRUE);
6908 if (pi) pi->generated = 1;
6911 /*-----------------------------------------------------------------*/
6912 /* genPagedPointerGet - emitcode for paged pointer fetch */
6913 /*-----------------------------------------------------------------*/
6915 genPagedPointerGet (operand * left,
6923 sym_link *rtype, *retype;
6925 rtype = operandType (result);
6926 retype = getSpec (rtype);
6928 aopOp (left, ic, FALSE);
6930 /* if the value is already in a pointer register
6931 then don't need anything more */
6932 if (!AOP_INPREG (AOP (left)))
6934 /* otherwise get a free pointer register */
6936 preg = getFreePtr (ic, &aop, FALSE);
6937 emitcode ("mov", "%s,%s",
6939 aopGet (AOP (left), 0, FALSE, TRUE));
6943 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6945 aopOp (result, ic, FALSE);
6947 /* if bitfield then unpack the bits */
6948 if (IS_BITVAR (retype))
6949 genUnpackBits (result, rname, PPOINTER);
6952 /* we have can just get the values */
6953 int size = AOP_SIZE (result);
6959 emitcode ("movx", "a,@%s", rname);
6960 aopPut (AOP (result), "a", offset);
6965 emitcode ("inc", "%s", rname);
6969 /* now some housekeeping stuff */
6970 if (aop) /* we had to allocate for this iCode */
6972 if (pi) aopPut ( AOP (left), rname, 0);
6973 freeAsmop (NULL, aop, ic, TRUE);
6977 /* we did not allocate which means left
6978 already in a pointer register, then
6979 if size > 0 && this could be used again
6980 we have to point it back to where it
6982 if ((AOP_SIZE (result) > 1 &&
6983 !OP_SYMBOL (left)->remat &&
6984 (OP_SYMBOL (left)->liveTo > ic->seq ||
6988 int size = AOP_SIZE (result) - 1;
6990 emitcode ("dec", "%s", rname);
6995 freeAsmop (left, NULL, ic, TRUE);
6996 freeAsmop (result, NULL, ic, TRUE);
6997 if (pi) pi->generated = 1;
7001 /*-----------------------------------------------------------------*/
7002 /* genFarPointerGet - gget value from far space */
7003 /*-----------------------------------------------------------------*/
7005 genFarPointerGet (operand * left,
7006 operand * result, iCode * ic, iCode * pi)
7009 sym_link *retype = getSpec (operandType (result));
7011 aopOp (left, ic, FALSE);
7013 /* if the operand is already in dptr
7014 then we do nothing else we move the value to dptr */
7015 if (AOP_TYPE (left) != AOP_STR)
7017 /* if this is remateriazable */
7018 if (AOP_TYPE (left) == AOP_IMMD)
7019 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7021 { /* we need to get it byte by byte */
7022 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7023 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7026 /* so dptr know contains the address */
7027 aopOp (result, ic, FALSE);
7029 /* if bit then unpack */
7030 if (IS_BITVAR (retype))
7031 genUnpackBits (result, "dptr", FPOINTER);
7034 size = AOP_SIZE (result);
7039 emitcode ("movx", "a,@dptr");
7040 aopPut (AOP (result), "a", offset++);
7042 emitcode ("inc", "dptr");
7046 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7047 aopPut ( AOP (left), "dpl", 0);
7048 aopPut ( AOP (left), "dph", 1);
7051 freeAsmop (left, NULL, ic, TRUE);
7052 freeAsmop (result, NULL, ic, TRUE);
7055 /*-----------------------------------------------------------------*/
7056 /* genCodePointerGet - gget value from code space */
7057 /*-----------------------------------------------------------------*/
7059 genCodePointerGet (operand * left,
7060 operand * result, iCode * ic, iCode *pi)
7063 sym_link *retype = getSpec (operandType (result));
7065 aopOp (left, ic, FALSE);
7067 /* if the operand is already in dptr
7068 then we do nothing else we move the value to dptr */
7069 if (AOP_TYPE (left) != AOP_STR)
7071 /* if this is remateriazable */
7072 if (AOP_TYPE (left) == AOP_IMMD)
7073 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7075 { /* we need to get it byte by byte */
7076 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7077 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7080 /* so dptr know contains the address */
7081 aopOp (result, ic, FALSE);
7083 /* if bit then unpack */
7084 if (IS_BITVAR (retype))
7085 genUnpackBits (result, "dptr", CPOINTER);
7088 size = AOP_SIZE (result);
7093 emitcode ("clr", "a");
7094 emitcode ("movc", "a,@a+dptr");
7095 aopPut (AOP (result), "a", offset++);
7097 emitcode ("inc", "dptr");
7101 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7102 aopPut ( AOP (left), "dpl", 0);
7103 aopPut ( AOP (left), "dph", 1);
7106 freeAsmop (left, NULL, ic, TRUE);
7107 freeAsmop (result, NULL, ic, TRUE);
7110 /*-----------------------------------------------------------------*/
7111 /* genGenPointerGet - gget value from generic pointer space */
7112 /*-----------------------------------------------------------------*/
7114 genGenPointerGet (operand * left,
7115 operand * result, iCode * ic, iCode *pi)
7118 sym_link *retype = getSpec (operandType (result));
7120 aopOp (left, ic, FALSE);
7122 /* if the operand is already in dptr
7123 then we do nothing else we move the value to dptr */
7124 if (AOP_TYPE (left) != AOP_STR)
7126 /* if this is remateriazable */
7127 if (AOP_TYPE (left) == AOP_IMMD)
7129 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7130 emitcode ("mov", "b,#%d", pointerCode (retype));
7133 { /* we need to get it byte by byte */
7134 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7135 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7136 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7139 /* so dptr know contains the address */
7140 aopOp (result, ic, FALSE);
7142 /* if bit then unpack */
7143 if (IS_BITVAR (retype))
7144 genUnpackBits (result, "dptr", GPOINTER);
7147 size = AOP_SIZE (result);
7152 emitcode ("lcall", "__gptrget");
7153 aopPut (AOP (result), "a", offset++);
7155 emitcode ("inc", "dptr");
7159 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7160 aopPut ( AOP (left), "dpl", 0);
7161 aopPut ( AOP (left), "dph", 1);
7164 freeAsmop (left, NULL, ic, TRUE);
7165 freeAsmop (result, NULL, ic, TRUE);
7168 /*-----------------------------------------------------------------*/
7169 /* genPointerGet - generate code for pointer get */
7170 /*-----------------------------------------------------------------*/
7172 genPointerGet (iCode * ic, iCode *pi)
7174 operand *left, *result;
7175 sym_link *type, *etype;
7178 left = IC_LEFT (ic);
7179 result = IC_RESULT (ic);
7181 /* depending on the type of pointer we need to
7182 move it to the correct pointer register */
7183 type = operandType (left);
7184 etype = getSpec (type);
7185 /* if left is of type of pointer then it is simple */
7186 if (IS_PTR (type) && !IS_FUNC (type->next))
7187 p_type = DCL_TYPE (type);
7190 /* we have to go by the storage class */
7191 p_type = PTR_TYPE (SPEC_OCLS (etype));
7194 /* now that we have the pointer type we assign
7195 the pointer values */
7201 genNearPointerGet (left, result, ic, pi);
7205 genPagedPointerGet (left, result, ic, pi);
7209 genFarPointerGet (left, result, ic, pi);
7213 genCodePointerGet (left, result, ic, pi);
7217 genGenPointerGet (left, result, ic, pi);
7223 /*-----------------------------------------------------------------*/
7224 /* genPackBits - generates code for packed bit storage */
7225 /*-----------------------------------------------------------------*/
7227 genPackBits (sym_link * etype,
7229 char *rname, int p_type)
7237 blen = SPEC_BLEN (etype);
7238 bstr = SPEC_BSTR (etype);
7240 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7243 /* if the bit lenth is less than or */
7244 /* it exactly fits a byte then */
7245 if (SPEC_BLEN (etype) <= 8)
7247 shCount = SPEC_BSTR (etype);
7249 /* shift left acc */
7252 if (SPEC_BLEN (etype) < 8)
7253 { /* if smaller than a byte */
7259 emitcode ("mov", "b,a");
7260 emitcode ("mov", "a,@%s", rname);
7264 emitcode ("mov", "b,a");
7265 emitcode ("movx", "a,@dptr");
7269 emitcode ("push", "b");
7270 emitcode ("push", "acc");
7271 emitcode ("lcall", "__gptrget");
7272 emitcode ("pop", "b");
7276 emitcode ("anl", "a,#0x%02x", (unsigned char)
7277 ((unsigned char) (0xFF << (blen + bstr)) |
7278 (unsigned char) (0xFF >> (8 - bstr))));
7279 emitcode ("orl", "a,b");
7280 if (p_type == GPOINTER)
7281 emitcode ("pop", "b");
7288 emitcode ("mov", "@%s,a", rname);
7292 emitcode ("movx", "@dptr,a");
7296 emitcode ("lcall", "__gptrput");
7301 if (SPEC_BLEN (etype) <= 8)
7304 emitcode ("inc", "%s", rname);
7305 rLen = SPEC_BLEN (etype);
7307 /* now generate for lengths greater than one byte */
7311 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7323 emitcode ("mov", "@%s,a", rname);
7326 emitcode ("mov", "@%s,%s", rname, l);
7331 emitcode ("movx", "@dptr,a");
7336 emitcode ("lcall", "__gptrput");
7339 emitcode ("inc", "%s", rname);
7344 /* last last was not complete */
7347 /* save the byte & read byte */
7351 emitcode ("mov", "b,a");
7352 emitcode ("mov", "a,@%s", rname);
7356 emitcode ("mov", "b,a");
7357 emitcode ("movx", "a,@dptr");
7361 emitcode ("push", "b");
7362 emitcode ("push", "acc");
7363 emitcode ("lcall", "__gptrget");
7364 emitcode ("pop", "b");
7368 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7369 emitcode ("orl", "a,b");
7372 if (p_type == GPOINTER)
7373 emitcode ("pop", "b");
7379 emitcode ("mov", "@%s,a", rname);
7383 emitcode ("movx", "@dptr,a");
7387 emitcode ("lcall", "__gptrput");
7391 /*-----------------------------------------------------------------*/
7392 /* genDataPointerSet - remat pointer to data space */
7393 /*-----------------------------------------------------------------*/
7395 genDataPointerSet (operand * right,
7399 int size, offset = 0;
7400 char *l, buffer[256];
7402 aopOp (right, ic, FALSE);
7404 l = aopGet (AOP (result), 0, FALSE, TRUE);
7405 size = AOP_SIZE (right);
7409 sprintf (buffer, "(%s + %d)", l + 1, offset);
7411 sprintf (buffer, "%s", l + 1);
7412 emitcode ("mov", "%s,%s", buffer,
7413 aopGet (AOP (right), offset++, FALSE, FALSE));
7416 freeAsmop (right, NULL, ic, TRUE);
7417 freeAsmop (result, NULL, ic, TRUE);
7420 /*-----------------------------------------------------------------*/
7421 /* genNearPointerSet - emitcode for near pointer put */
7422 /*-----------------------------------------------------------------*/
7424 genNearPointerSet (operand * right,
7432 sym_link *retype, *letype;
7433 sym_link *ptype = operandType (result);
7435 retype = getSpec (operandType (right));
7436 letype = getSpec (ptype);
7437 aopOp (result, ic, FALSE);
7439 /* if the result is rematerializable &
7440 in data space & not a bit variable */
7441 if (AOP_TYPE (result) == AOP_IMMD &&
7442 DCL_TYPE (ptype) == POINTER &&
7443 !IS_BITVAR (retype) &&
7444 !IS_BITVAR (letype))
7446 genDataPointerSet (right, result, ic);
7450 /* if the value is already in a pointer register
7451 then don't need anything more */
7452 if (!AOP_INPREG (AOP (result)))
7454 /* otherwise get a free pointer register */
7456 preg = getFreePtr (ic, &aop, FALSE);
7457 emitcode ("mov", "%s,%s",
7459 aopGet (AOP (result), 0, FALSE, TRUE));
7463 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7465 aopOp (right, ic, FALSE);
7467 /* if bitfield then unpack the bits */
7468 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7469 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7472 /* we have can just get the values */
7473 int size = AOP_SIZE (right);
7478 l = aopGet (AOP (right), offset, FALSE, TRUE);
7482 emitcode ("mov", "@%s,a", rname);
7485 emitcode ("mov", "@%s,%s", rname, l);
7487 emitcode ("inc", "%s", rname);
7492 /* now some housekeeping stuff */
7493 if (aop) /* we had to allocate for this iCode */
7495 if (pi) aopPut (AOP (result),rname,0);
7496 freeAsmop (NULL, aop, ic, TRUE);
7500 /* we did not allocate which means left
7501 already in a pointer register, then
7502 if size > 0 && this could be used again
7503 we have to point it back to where it
7505 if ((AOP_SIZE (right) > 1 &&
7506 !OP_SYMBOL (result)->remat &&
7507 (OP_SYMBOL (result)->liveTo > ic->seq ||
7511 int size = AOP_SIZE (right) - 1;
7513 emitcode ("dec", "%s", rname);
7518 if (pi) pi->generated = 1;
7519 freeAsmop (result, NULL, ic, TRUE);
7520 freeAsmop (right, NULL, ic, TRUE);
7523 /*-----------------------------------------------------------------*/
7524 /* genPagedPointerSet - emitcode for Paged pointer put */
7525 /*-----------------------------------------------------------------*/
7527 genPagedPointerSet (operand * right,
7535 sym_link *retype, *letype;
7537 retype = getSpec (operandType (right));
7538 letype = getSpec (operandType (result));
7540 aopOp (result, ic, FALSE);
7542 /* if the value is already in a pointer register
7543 then don't need anything more */
7544 if (!AOP_INPREG (AOP (result)))
7546 /* otherwise get a free pointer register */
7548 preg = getFreePtr (ic, &aop, FALSE);
7549 emitcode ("mov", "%s,%s",
7551 aopGet (AOP (result), 0, FALSE, TRUE));
7555 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7557 aopOp (right, ic, FALSE);
7559 /* if bitfield then unpack the bits */
7560 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7561 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7564 /* we have can just get the values */
7565 int size = AOP_SIZE (right);
7570 l = aopGet (AOP (right), offset, FALSE, TRUE);
7573 emitcode ("movx", "@%s,a", rname);
7576 emitcode ("inc", "%s", rname);
7582 /* now some housekeeping stuff */
7583 if (aop) /* we had to allocate for this iCode */
7585 if (pi) aopPut (AOP (result),rname,0);
7586 freeAsmop (NULL, aop, ic, TRUE);
7590 /* we did not allocate which means left
7591 already in a pointer register, then
7592 if size > 0 && this could be used again
7593 we have to point it back to where it
7595 if (AOP_SIZE (right) > 1 &&
7596 !OP_SYMBOL (result)->remat &&
7597 (OP_SYMBOL (result)->liveTo > ic->seq ||
7600 int size = AOP_SIZE (right) - 1;
7602 emitcode ("dec", "%s", rname);
7607 if (pi) pi->generated = 1;
7608 freeAsmop (result, NULL, ic, TRUE);
7609 freeAsmop (right, NULL, ic, TRUE);
7614 /*-----------------------------------------------------------------*/
7615 /* genFarPointerSet - set value from far space */
7616 /*-----------------------------------------------------------------*/
7618 genFarPointerSet (operand * right,
7619 operand * result, iCode * ic, iCode * pi)
7622 sym_link *retype = getSpec (operandType (right));
7623 sym_link *letype = getSpec (operandType (result));
7624 aopOp (result, ic, FALSE);
7626 /* if the operand is already in dptr
7627 then we do nothing else we move the value to dptr */
7628 if (AOP_TYPE (result) != AOP_STR)
7630 /* if this is remateriazable */
7631 if (AOP_TYPE (result) == AOP_IMMD)
7632 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7634 { /* we need to get it byte by byte */
7635 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7636 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7639 /* so dptr know contains the address */
7640 aopOp (right, ic, FALSE);
7642 /* if bit then unpack */
7643 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7644 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7647 size = AOP_SIZE (right);
7652 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7654 emitcode ("movx", "@dptr,a");
7656 emitcode ("inc", "dptr");
7659 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7660 aopPut (AOP(result),"dpl",0);
7661 aopPut (AOP(result),"dph",1);
7664 freeAsmop (result, NULL, ic, TRUE);
7665 freeAsmop (right, NULL, ic, TRUE);
7668 /*-----------------------------------------------------------------*/
7669 /* genGenPointerSet - set value from generic pointer space */
7670 /*-----------------------------------------------------------------*/
7672 genGenPointerSet (operand * right,
7673 operand * result, iCode * ic, iCode * pi)
7676 sym_link *retype = getSpec (operandType (right));
7677 sym_link *letype = getSpec (operandType (result));
7679 aopOp (result, ic, FALSE);
7681 /* if the operand is already in dptr
7682 then we do nothing else we move the value to dptr */
7683 if (AOP_TYPE (result) != AOP_STR)
7685 /* if this is remateriazable */
7686 if (AOP_TYPE (result) == AOP_IMMD)
7688 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7689 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7692 { /* we need to get it byte by byte */
7693 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7694 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7695 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7698 /* so dptr know contains the address */
7699 aopOp (right, ic, FALSE);
7701 /* if bit then unpack */
7702 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7703 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7706 size = AOP_SIZE (right);
7711 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7713 emitcode ("lcall", "__gptrput");
7715 emitcode ("inc", "dptr");
7719 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7720 aopPut (AOP(result),"dpl",0);
7721 aopPut (AOP(result),"dph",1);
7724 freeAsmop (result, NULL, ic, TRUE);
7725 freeAsmop (right, NULL, ic, TRUE);
7728 /*-----------------------------------------------------------------*/
7729 /* genPointerSet - stores the value into a pointer location */
7730 /*-----------------------------------------------------------------*/
7732 genPointerSet (iCode * ic, iCode *pi)
7734 operand *right, *result;
7735 sym_link *type, *etype;
7738 right = IC_RIGHT (ic);
7739 result = IC_RESULT (ic);
7741 /* depending on the type of pointer we need to
7742 move it to the correct pointer register */
7743 type = operandType (result);
7744 etype = getSpec (type);
7745 /* if left is of type of pointer then it is simple */
7746 if (IS_PTR (type) && !IS_FUNC (type->next))
7748 p_type = DCL_TYPE (type);
7752 /* we have to go by the storage class */
7753 p_type = PTR_TYPE (SPEC_OCLS (etype));
7756 /* now that we have the pointer type we assign
7757 the pointer values */
7763 genNearPointerSet (right, result, ic, pi);
7767 genPagedPointerSet (right, result, ic, pi);
7771 genFarPointerSet (right, result, ic, pi);
7775 genGenPointerSet (right, result, ic, pi);
7781 /*-----------------------------------------------------------------*/
7782 /* genIfx - generate code for Ifx statement */
7783 /*-----------------------------------------------------------------*/
7785 genIfx (iCode * ic, iCode * popIc)
7787 operand *cond = IC_COND (ic);
7790 aopOp (cond, ic, FALSE);
7792 /* get the value into acc */
7793 if (AOP_TYPE (cond) != AOP_CRY)
7797 /* the result is now in the accumulator */
7798 freeAsmop (cond, NULL, ic, TRUE);
7800 /* if there was something to be popped then do it */
7804 /* if the condition is a bit variable */
7805 if (isbit && IS_ITEMP (cond) &&
7807 genIfxJump (ic, SPIL_LOC (cond)->rname);
7808 else if (isbit && !IS_ITEMP (cond))
7809 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7811 genIfxJump (ic, "a");
7816 /*-----------------------------------------------------------------*/
7817 /* genAddrOf - generates code for address of */
7818 /*-----------------------------------------------------------------*/
7820 genAddrOf (iCode * ic)
7822 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7825 aopOp (IC_RESULT (ic), ic, FALSE);
7827 /* if the operand is on the stack then we
7828 need to get the stack offset of this
7832 /* if it has an offset then we need to compute
7836 emitcode ("mov", "a,_bp");
7837 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7838 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7842 /* we can just move _bp */
7843 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7845 /* fill the result with zero */
7846 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7851 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7857 /* object not on stack then we need the name */
7858 size = AOP_SIZE (IC_RESULT (ic));
7863 char s[SDCC_NAME_MAX];
7865 sprintf (s, "#(%s >> %d)",
7869 sprintf (s, "#%s", sym->rname);
7870 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7878 /*-----------------------------------------------------------------*/
7879 /* genFarFarAssign - assignment when both are in far space */
7880 /*-----------------------------------------------------------------*/
7882 genFarFarAssign (operand * result, operand * right, iCode * ic)
7884 int size = AOP_SIZE (right);
7887 /* first push the right side on to the stack */
7890 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7892 emitcode ("push", "acc");
7895 freeAsmop (right, NULL, ic, FALSE);
7896 /* now assign DPTR to result */
7897 aopOp (result, ic, FALSE);
7898 size = AOP_SIZE (result);
7901 emitcode ("pop", "acc");
7902 aopPut (AOP (result), "a", --offset);
7904 freeAsmop (result, NULL, ic, FALSE);
7908 /*-----------------------------------------------------------------*/
7909 /* genAssign - generate code for assignment */
7910 /*-----------------------------------------------------------------*/
7912 genAssign (iCode * ic)
7914 operand *result, *right;
7916 unsigned long lit = 0L;
7918 result = IC_RESULT (ic);
7919 right = IC_RIGHT (ic);
7921 /* if they are the same */
7922 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7925 aopOp (right, ic, FALSE);
7927 /* special case both in far space */
7928 if (AOP_TYPE (right) == AOP_DPTR &&
7929 IS_TRUE_SYMOP (result) &&
7930 isOperandInFarSpace (result))
7933 genFarFarAssign (result, right, ic);
7937 aopOp (result, ic, TRUE);
7939 /* if they are the same registers */
7940 if (sameRegs (AOP (right), AOP (result)))
7943 /* if the result is a bit */
7944 if (AOP_TYPE (result) == AOP_CRY)
7947 /* if the right size is a literal then
7948 we know what the value is */
7949 if (AOP_TYPE (right) == AOP_LIT)
7951 if (((int) operandLitValue (right)))
7952 aopPut (AOP (result), one, 0);
7954 aopPut (AOP (result), zero, 0);
7958 /* the right is also a bit variable */
7959 if (AOP_TYPE (right) == AOP_CRY)
7961 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7962 aopPut (AOP (result), "c", 0);
7968 aopPut (AOP (result), "a", 0);
7972 /* bit variables done */
7974 size = AOP_SIZE (result);
7976 if (AOP_TYPE (right) == AOP_LIT)
7977 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7979 (AOP_TYPE (result) != AOP_REG) &&
7980 (AOP_TYPE (right) == AOP_LIT) &&
7981 !IS_FLOAT (operandType (right)) &&
7984 emitcode ("clr", "a");
7987 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7988 aopPut (AOP (result), "a", size);
7990 aopPut (AOP (result),
7991 aopGet (AOP (right), size, FALSE, FALSE),
7999 aopPut (AOP (result),
8000 aopGet (AOP (right), offset, FALSE, FALSE),
8007 freeAsmop (right, NULL, ic, TRUE);
8008 freeAsmop (result, NULL, ic, TRUE);
8011 /*-----------------------------------------------------------------*/
8012 /* genJumpTab - genrates code for jump table */
8013 /*-----------------------------------------------------------------*/
8015 genJumpTab (iCode * ic)
8020 aopOp (IC_JTCOND (ic), ic, FALSE);
8021 /* get the condition into accumulator */
8022 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8024 /* multiply by three */
8025 emitcode ("add", "a,acc");
8026 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8027 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8029 jtab = newiTempLabel (NULL);
8030 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8031 emitcode ("jmp", "@a+dptr");
8032 emitcode ("", "%05d$:", jtab->key + 100);
8033 /* now generate the jump labels */
8034 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8035 jtab = setNextItem (IC_JTLABELS (ic)))
8036 emitcode ("ljmp", "%05d$", jtab->key + 100);
8040 /*-----------------------------------------------------------------*/
8041 /* genCast - gen code for casting */
8042 /*-----------------------------------------------------------------*/
8044 genCast (iCode * ic)
8046 operand *result = IC_RESULT (ic);
8047 sym_link *ctype = operandType (IC_LEFT (ic));
8048 sym_link *rtype = operandType (IC_RIGHT (ic));
8049 operand *right = IC_RIGHT (ic);
8052 /* if they are equivalent then do nothing */
8053 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8056 aopOp (right, ic, FALSE);
8057 aopOp (result, ic, FALSE);
8059 /* if the result is a bit */
8060 if (AOP_TYPE (result) == AOP_CRY)
8062 /* if the right size is a literal then
8063 we know what the value is */
8064 if (AOP_TYPE (right) == AOP_LIT)
8066 if (((int) operandLitValue (right)))
8067 aopPut (AOP (result), one, 0);
8069 aopPut (AOP (result), zero, 0);
8074 /* the right is also a bit variable */
8075 if (AOP_TYPE (right) == AOP_CRY)
8077 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8078 aopPut (AOP (result), "c", 0);
8084 aopPut (AOP (result), "a", 0);
8088 /* if they are the same size : or less */
8089 if (AOP_SIZE (result) <= AOP_SIZE (right))
8092 /* if they are in the same place */
8093 if (sameRegs (AOP (right), AOP (result)))
8096 /* if they in different places then copy */
8097 size = AOP_SIZE (result);
8101 aopPut (AOP (result),
8102 aopGet (AOP (right), offset, FALSE, FALSE),
8110 /* if the result is of type pointer */
8115 sym_link *type = operandType (right);
8116 sym_link *etype = getSpec (type);
8118 /* pointer to generic pointer */
8119 if (IS_GENPTR (ctype))
8124 p_type = DCL_TYPE (type);
8127 /* we have to go by the storage class */
8128 p_type = PTR_TYPE (SPEC_OCLS (etype));
8131 /* the first two bytes are known */
8132 size = GPTRSIZE - 1;
8136 aopPut (AOP (result),
8137 aopGet (AOP (right), offset, FALSE, FALSE),
8141 /* the last byte depending on type */
8159 /* this should never happen */
8160 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8161 "got unknown pointer type");
8164 aopPut (AOP (result), l, GPTRSIZE - 1);
8168 /* just copy the pointers */
8169 size = AOP_SIZE (result);
8173 aopPut (AOP (result),
8174 aopGet (AOP (right), offset, FALSE, FALSE),
8181 /* so we now know that the size of destination is greater
8182 than the size of the source */
8183 /* we move to result for the size of source */
8184 size = AOP_SIZE (right);
8188 aopPut (AOP (result),
8189 aopGet (AOP (right), offset, FALSE, FALSE),
8194 /* now depending on the sign of the source && destination */
8195 size = AOP_SIZE (result) - AOP_SIZE (right);
8196 /* if unsigned or not an integral type */
8197 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8200 aopPut (AOP (result), zero, offset++);
8204 /* we need to extend the sign :{ */
8205 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8208 emitcode ("rlc", "a");
8209 emitcode ("subb", "a,acc");
8211 aopPut (AOP (result), "a", offset++);
8214 /* we are done hurray !!!! */
8217 freeAsmop (right, NULL, ic, TRUE);
8218 freeAsmop (result, NULL, ic, TRUE);
8222 /*-----------------------------------------------------------------*/
8223 /* genDjnz - generate decrement & jump if not zero instrucion */
8224 /*-----------------------------------------------------------------*/
8226 genDjnz (iCode * ic, iCode * ifx)
8232 /* if the if condition has a false label
8233 then we cannot save */
8237 /* if the minus is not of the form
8239 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8240 !IS_OP_LITERAL (IC_RIGHT (ic)))
8243 if (operandLitValue (IC_RIGHT (ic)) != 1)
8246 /* if the size of this greater than one then no
8248 if (getSize (operandType (IC_RESULT (ic))) > 1)
8251 /* otherwise we can save BIG */
8252 lbl = newiTempLabel (NULL);
8253 lbl1 = newiTempLabel (NULL);
8255 aopOp (IC_RESULT (ic), ic, FALSE);
8257 if (AOP_NEEDSACC(IC_RESULT(ic)))
8259 /* If the result is accessed indirectly via
8260 * the accumulator, we must explicitly write
8261 * it back after the decrement.
8263 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8265 if (strcmp(rByte, "a"))
8267 /* Something is hopelessly wrong */
8268 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8269 __FILE__, __LINE__);
8270 /* We can just give up; the generated code will be inefficient,
8273 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8276 emitcode ("dec", "%s", rByte);
8277 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8278 emitcode ("jnz", "%05d$", lbl->key + 100);
8280 else if (IS_AOP_PREG (IC_RESULT (ic)))
8282 emitcode ("dec", "%s",
8283 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8284 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8285 emitcode ("jnz", "%05d$", lbl->key + 100);
8289 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8292 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8293 emitcode ("", "%05d$:", lbl->key + 100);
8294 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8295 emitcode ("", "%05d$:", lbl1->key + 100);
8297 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8302 /*-----------------------------------------------------------------*/
8303 /* genReceive - generate code for a receive iCode */
8304 /*-----------------------------------------------------------------*/
8306 genReceive (iCode * ic)
8308 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8309 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8310 IS_TRUE_SYMOP (IC_RESULT (ic))))
8313 int size = getSize (operandType (IC_RESULT (ic)));
8314 int offset = fReturnSizeMCS51 - size;
8317 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8318 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8321 aopOp (IC_RESULT (ic), ic, FALSE);
8322 size = AOP_SIZE (IC_RESULT (ic));
8326 emitcode ("pop", "acc");
8327 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8334 aopOp (IC_RESULT (ic), ic, FALSE);
8336 assignResultValue (IC_RESULT (ic));
8339 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8342 /*-----------------------------------------------------------------*/
8343 /* gen51Code - generate code for 8051 based controllers */
8344 /*-----------------------------------------------------------------*/
8346 gen51Code (iCode * lic)
8351 lineHead = lineCurr = NULL;
8353 /* print the allocation information */
8355 printAllocInfo (currFunc, codeOutFile);
8356 /* if debug information required */
8357 /* if (options.debug && currFunc) { */
8360 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8362 if (IS_STATIC (currFunc->etype))
8363 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8365 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8368 /* stack pointer name */
8369 if (options.useXstack)
8375 for (ic = lic; ic; ic = ic->next)
8378 if (cln != ic->lineno)
8383 emitcode ("", "C$%s$%d$%d$%d ==.",
8384 FileBaseName (ic->filename), ic->lineno,
8385 ic->level, ic->block);
8388 emitcode (";", "%s %d", ic->filename, ic->lineno);
8391 /* if the result is marked as
8392 spilt and rematerializable or code for
8393 this has already been generated then
8395 if (resultRemat (ic) || ic->generated)
8398 /* depending on the operation */
8418 /* IPOP happens only when trying to restore a
8419 spilt live range, if there is an ifx statement
8420 following this pop then the if statement might
8421 be using some of the registers being popped which
8422 would destory the contents of the register so
8423 we need to check for this condition and handle it */
8425 ic->next->op == IFX &&
8426 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8427 genIfx (ic->next, ic);
8445 genEndFunction (ic);
8465 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8482 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8486 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8493 /* note these two are xlated by algebraic equivalence
8494 during parsing SDCC.y */
8495 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8496 "got '>=' or '<=' shouldn't have come here");
8500 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8512 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8516 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8520 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8547 case GET_VALUE_AT_ADDRESS:
8548 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8552 if (POINTER_SET (ic))
8553 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8579 addSet (&_G.sendSet, ic);
8588 /* now we are ready to call the
8589 peep hole optimizer */
8590 if (!options.nopeep)
8591 peepHole (&lineHead);
8593 /* now do the actual printing */
8594 printLine (lineHead, codeOutFile);