1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[INITIAL_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1451 /* find the registers in use at this time
1452 and push them away to safety */
1453 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1457 if (options.useXstack)
1459 if (bitVectBitValue (rsave, R0_IDX))
1460 emitcode ("mov", "b,r0");
1461 emitcode ("mov", "r0,%s", spname);
1462 for (i = 0; i < mcs51_nRegs; i++)
1464 if (bitVectBitValue (rsave, i))
1467 emitcode ("mov", "a,b");
1469 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1470 emitcode ("movx", "@r0,a");
1471 emitcode ("inc", "r0");
1474 emitcode ("mov", "%s,r0", spname);
1475 if (bitVectBitValue (rsave, R0_IDX))
1476 emitcode ("mov", "r0,b");
1479 for (i = 0; i < mcs51_nRegs; i++)
1481 if (bitVectBitValue (rsave, i))
1482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1485 detype = getSpec (operandType (IC_LEFT (ic)));
1487 #if 0 // why should we do this here??? jwk20011105
1489 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1490 IS_ISR (currFunc->etype) &&
1492 saveRBank (SPEC_BANK (detype), ic, TRUE);
1496 /*-----------------------------------------------------------------*/
1497 /* unsaveRegisters - pop the pushed registers */
1498 /*-----------------------------------------------------------------*/
1500 unsaveRegisters (iCode * ic)
1504 /* find the registers in use at this time
1505 and push them away to safety */
1506 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1509 if (options.useXstack)
1511 emitcode ("mov", "r0,%s", spname);
1512 for (i = mcs51_nRegs; i >= 0; i--)
1514 if (bitVectBitValue (rsave, i))
1516 emitcode ("dec", "r0");
1517 emitcode ("movx", "a,@r0");
1519 emitcode ("mov", "b,a");
1521 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = mcs51_nRegs; i >= 0; i--)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1539 /*-----------------------------------------------------------------*/
1541 /*-----------------------------------------------------------------*/
1543 pushSide (operand * oper, int size)
1548 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1549 if (AOP_TYPE (oper) != AOP_REG &&
1550 AOP_TYPE (oper) != AOP_DIR &&
1553 emitcode ("mov", "a,%s", l);
1554 emitcode ("push", "acc");
1557 emitcode ("push", "%s", l);
1561 /*-----------------------------------------------------------------*/
1562 /* assignResultValue - */
1563 /*-----------------------------------------------------------------*/
1565 assignResultValue (operand * oper)
1568 int size = AOP_SIZE (oper);
1571 aopPut (AOP (oper), fReturn[offset], offset);
1577 /*-----------------------------------------------------------------*/
1578 /* genXpush - pushes onto the external stack */
1579 /*-----------------------------------------------------------------*/
1581 genXpush (iCode * ic)
1583 asmop *aop = newAsmop (0);
1585 int size, offset = 0;
1587 aopOp (IC_LEFT (ic), ic, FALSE);
1588 r = getFreePtr (ic, &aop, FALSE);
1591 emitcode ("mov", "%s,_spx", r->name);
1593 size = AOP_SIZE (IC_LEFT (ic));
1597 char *l = aopGet (AOP (IC_LEFT (ic)),
1598 offset++, FALSE, FALSE);
1600 emitcode ("movx", "@%s,a", r->name);
1601 emitcode ("inc", "%s", r->name);
1606 emitcode ("mov", "_spx,%s", r->name);
1608 freeAsmop (NULL, aop, ic, TRUE);
1609 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1612 /*-----------------------------------------------------------------*/
1613 /* genIpush - genrate code for pushing this gets a little complex */
1614 /*-----------------------------------------------------------------*/
1616 genIpush (iCode * ic)
1618 int size, offset = 0;
1621 /* if this is not a parm push : ie. it is spill push
1622 and spill push is always done on the local stack */
1626 /* and the item is spilt then do nothing */
1627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1630 aopOp (IC_LEFT (ic), ic, FALSE);
1631 size = AOP_SIZE (IC_LEFT (ic));
1632 /* push it on the stack */
1635 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1641 emitcode ("push", "%s", l);
1646 /* this is a paramter push: in this case we call
1647 the routine to find the call and save those
1648 registers that need to be saved */
1651 /* if use external stack then call the external
1652 stack pushing routine */
1653 if (options.useXstack)
1659 /* then do the push */
1660 aopOp (IC_LEFT (ic), ic, FALSE);
1663 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1664 size = AOP_SIZE (IC_LEFT (ic));
1668 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1669 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1670 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1673 emitcode ("mov", "a,%s", l);
1674 emitcode ("push", "acc");
1677 emitcode ("push", "%s", l);
1680 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1683 /*-----------------------------------------------------------------*/
1684 /* genIpop - recover the registers: can happen only for spilling */
1685 /*-----------------------------------------------------------------*/
1687 genIpop (iCode * ic)
1692 /* if the temp was not pushed then */
1693 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1696 aopOp (IC_LEFT (ic), ic, FALSE);
1697 size = AOP_SIZE (IC_LEFT (ic));
1698 offset = (size - 1);
1700 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1703 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* unsaveRBank - restores the resgister bank from stack */
1708 /*-----------------------------------------------------------------*/
1710 unsaveRBank (int bank, iCode * ic, bool popPsw)
1716 if (options.useXstack)
1720 /* Assume r0 is available for use. */
1721 r = mcs51_regWithIdx (R0_IDX);;
1726 r = getFreePtr (ic, &aop, FALSE);
1728 emitcode ("mov", "%s,_spx", r->name);
1733 if (options.useXstack)
1735 emitcode ("movx", "a,@%s", r->name);
1736 emitcode ("mov", "psw,a");
1737 emitcode ("dec", "%s", r->name);
1741 emitcode ("pop", "psw");
1745 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1747 if (options.useXstack)
1749 emitcode ("movx", "a,@%s", r->name);
1750 emitcode ("mov", "(%s+%d),a",
1751 regs8051[i].base, 8 * bank + regs8051[i].offset);
1752 emitcode ("dec", "%s", r->name);
1756 emitcode ("pop", "(%s+%d)",
1757 regs8051[i].base, 8 * bank + regs8051[i].offset);
1760 if (options.useXstack)
1762 emitcode ("mov", "_spx,%s", r->name);
1767 freeAsmop (NULL, aop, ic, TRUE);
1771 /*-----------------------------------------------------------------*/
1772 /* saveRBank - saves an entire register bank on the stack */
1773 /*-----------------------------------------------------------------*/
1775 saveRBank (int bank, iCode * ic, bool pushPsw)
1781 if (options.useXstack)
1785 /* Assume r0 is available for use. */
1786 r = mcs51_regWithIdx (R0_IDX);;
1791 r = getFreePtr (ic, &aop, FALSE);
1793 emitcode ("mov", "%s,_spx", r->name);
1796 for (i = 0; i < mcs51_nRegs; i++)
1798 if (options.useXstack)
1800 emitcode ("inc", "%s", r->name);
1801 emitcode ("mov", "a,(%s+%d)",
1802 regs8051[i].base, 8 * bank + regs8051[i].offset);
1803 emitcode ("movx", "@%s,a", r->name);
1806 emitcode ("push", "(%s+%d)",
1807 regs8051[i].base, 8 * bank + regs8051[i].offset);
1812 if (options.useXstack)
1814 emitcode ("mov", "a,psw");
1815 emitcode ("movx", "@%s,a", r->name);
1816 emitcode ("inc", "%s", r->name);
1817 emitcode ("mov", "_spx,%s", r->name);
1822 emitcode ("push", "psw");
1825 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1830 freeAsmop (NULL, aop, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genCall - generates a call statement */
1841 /*-----------------------------------------------------------------*/
1843 genCall (iCode * ic)
1846 bool restoreBank = FALSE;
1847 bool swapBanks = FALSE;
1849 /* if send set is not empty the assign */
1854 for (sic = setFirstItem (_G.sendSet); sic;
1855 sic = setNextItem (_G.sendSet))
1857 int size, offset = 0;
1858 aopOp (IC_LEFT (sic), sic, FALSE);
1859 size = AOP_SIZE (IC_LEFT (sic));
1862 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1864 if (strcmp (l, fReturn[offset]))
1865 emitcode ("mov", "%s,%s",
1870 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1875 /* if we are calling a function that is not using
1876 the same register bank then we need to save the
1877 destination registers on the stack */
1878 detype = getSpec (operandType (IC_LEFT (ic)));
1880 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1881 IS_ISR (currFunc->etype))
1885 /* This is unexpected; the bank should have been saved in
1888 saveRBank (SPEC_BANK (detype), ic, FALSE);
1894 /* if caller saves & we have not saved then */
1900 emitcode ("mov", "psw,#0x%02x",
1901 ((SPEC_BANK(detype)) << 3) & 0xff);
1905 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1906 OP_SYMBOL (IC_LEFT (ic))->rname :
1907 OP_SYMBOL (IC_LEFT (ic))->name));
1911 emitcode ("mov", "psw,#0x%02x",
1912 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1915 /* if we need assign a result value */
1916 if ((IS_ITEMP (IC_RESULT (ic)) &&
1917 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1918 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1919 IS_TRUE_SYMOP (IC_RESULT (ic)))
1923 aopOp (IC_RESULT (ic), ic, FALSE);
1926 assignResultValue (IC_RESULT (ic));
1928 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1931 /* adjust the stack for parameters if
1936 if (ic->parmBytes > 3)
1938 emitcode ("mov", "a,%s", spname);
1939 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1940 emitcode ("mov", "%s,a", spname);
1943 for (i = 0; i < ic->parmBytes; i++)
1944 emitcode ("dec", "%s", spname);
1947 /* if we hade saved some registers then unsave them */
1948 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1949 unsaveRegisters (ic);
1951 /* if register bank was saved then pop them */
1953 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1956 /*-----------------------------------------------------------------*/
1957 /* genPcall - generates a call by pointer statement */
1958 /*-----------------------------------------------------------------*/
1960 genPcall (iCode * ic)
1963 symbol *rlbl = newiTempLabel (NULL);
1966 /* if caller saves & we have not saved then */
1970 /* if we are calling a function that is not using
1971 the same register bank then we need to save the
1972 destination registers on the stack */
1973 detype = getSpec (operandType (IC_LEFT (ic)));
1975 IS_ISR (currFunc->etype) &&
1976 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1977 saveRBank (SPEC_BANK (detype), ic, TRUE);
1980 /* push the return address on to the stack */
1981 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1982 emitcode ("push", "acc");
1983 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1984 emitcode ("push", "acc");
1986 /* now push the calling address */
1987 aopOp (IC_LEFT (ic), ic, FALSE);
1989 pushSide (IC_LEFT (ic), FPTRSIZE);
1991 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1993 /* if send set is not empty the assign */
1998 for (sic = setFirstItem (_G.sendSet); sic;
1999 sic = setNextItem (_G.sendSet))
2001 int size, offset = 0;
2002 aopOp (IC_LEFT (sic), sic, FALSE);
2003 size = AOP_SIZE (IC_LEFT (sic));
2006 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2008 if (strcmp (l, fReturn[offset]))
2009 emitcode ("mov", "%s,%s",
2014 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2019 emitcode ("ret", "");
2020 emitcode ("", "%05d$:", (rlbl->key + 100));
2023 /* if we need assign a result value */
2024 if ((IS_ITEMP (IC_RESULT (ic)) &&
2025 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2026 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2027 IS_TRUE_SYMOP (IC_RESULT (ic)))
2031 aopOp (IC_RESULT (ic), ic, FALSE);
2034 assignResultValue (IC_RESULT (ic));
2036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2039 /* adjust the stack for parameters if
2044 if (ic->parmBytes > 3)
2046 emitcode ("mov", "a,%s", spname);
2047 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2048 emitcode ("mov", "%s,a", spname);
2051 for (i = 0; i < ic->parmBytes; i++)
2052 emitcode ("dec", "%s", spname);
2056 /* if register bank was saved then unsave them */
2058 (SPEC_BANK (currFunc->etype) !=
2059 SPEC_BANK (detype)))
2060 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2062 /* if we hade saved some registers then
2065 unsaveRegisters (ic);
2069 /*-----------------------------------------------------------------*/
2070 /* resultRemat - result is rematerializable */
2071 /*-----------------------------------------------------------------*/
2073 resultRemat (iCode * ic)
2075 if (SKIP_IC (ic) || ic->op == IFX)
2078 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2080 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2081 if (sym->remat && !POINTER_SET (ic))
2088 #if defined(__BORLANDC__) || defined(_MSC_VER)
2089 #define STRCASECMP stricmp
2091 #define STRCASECMP strcasecmp
2094 /*-----------------------------------------------------------------*/
2095 /* inExcludeList - return 1 if the string is in exclude Reg list */
2096 /*-----------------------------------------------------------------*/
2098 inExcludeList (char *s)
2102 if (options.excludeRegs[i] &&
2103 STRCASECMP (options.excludeRegs[i], "none") == 0)
2106 for (i = 0; options.excludeRegs[i]; i++)
2108 if (options.excludeRegs[i] &&
2109 STRCASECMP (s, options.excludeRegs[i]) == 0)
2115 /*-----------------------------------------------------------------*/
2116 /* genFunction - generated code for function entry */
2117 /*-----------------------------------------------------------------*/
2119 genFunction (iCode * ic)
2123 bool switchedPSW = FALSE;
2126 /* create the function header */
2127 emitcode (";", "-----------------------------------------");
2128 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2129 emitcode (";", "-----------------------------------------");
2131 emitcode ("", "%s:", sym->rname);
2132 fetype = getSpec (operandType (IC_LEFT (ic)));
2134 /* if critical function then turn interrupts off */
2135 if (SPEC_CRTCL (fetype))
2136 emitcode ("clr", "ea");
2138 /* here we need to generate the equates for the
2139 register bank if required */
2140 if (SPEC_BANK (fetype) != rbank)
2144 rbank = SPEC_BANK (fetype);
2145 for (i = 0; i < mcs51_nRegs; i++)
2147 if (strcmp (regs8051[i].base, "0") == 0)
2148 emitcode ("", "%s = 0x%02x",
2150 8 * rbank + regs8051[i].offset);
2152 emitcode ("", "%s = %s + 0x%02x",
2155 8 * rbank + regs8051[i].offset);
2159 /* if this is an interrupt service routine then
2160 save acc, b, dpl, dph */
2161 if (IS_ISR (sym->etype))
2164 if (!inExcludeList ("acc"))
2165 emitcode ("push", "acc");
2166 if (!inExcludeList ("b"))
2167 emitcode ("push", "b");
2168 if (!inExcludeList ("dpl"))
2169 emitcode ("push", "dpl");
2170 if (!inExcludeList ("dph"))
2171 emitcode ("push", "dph");
2172 /* if this isr has no bank i.e. is going to
2173 run with bank 0 , then we need to save more
2175 if (!SPEC_BANK (sym->etype))
2178 /* if this function does not call any other
2179 function then we can be economical and
2180 save only those registers that are used */
2185 /* if any registers used */
2188 /* save the registers used */
2189 for (i = 0; i < sym->regsUsed->size; i++)
2191 if (bitVectBitValue (sym->regsUsed, i) ||
2192 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2193 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2200 /* this function has a function call cannot
2201 determines register usage so we will have to push the
2203 saveRBank (0, ic, FALSE);
2208 /* This ISR uses a non-zero bank.
2210 * We assume that the bank is available for our
2213 * However, if this ISR calls a function which uses some
2214 * other bank, we must save that bank entirely.
2216 unsigned long banksToSave = 0;
2221 #define MAX_REGISTER_BANKS 4
2226 for (i = ic; i; i = i->next)
2228 if (i->op == ENDFUNCTION)
2230 /* we got to the end OK. */
2238 detype = getSpec(operandType (IC_LEFT(i)));
2240 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2242 /* Mark this bank for saving. */
2243 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2245 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2249 banksToSave |= (1 << SPEC_BANK(detype));
2252 /* And note that we don't need to do it in
2260 /* This is a mess; we have no idea what
2261 * register bank the called function might
2264 * The only thing I can think of to do is
2265 * throw a warning and hope.
2267 werror(W_FUNCPTR_IN_USING_ISR);
2271 if (banksToSave && options.useXstack)
2273 /* Since we aren't passing it an ic,
2274 * saveRBank will assume r0 is available to abuse.
2276 * So switch to our (trashable) bank now, so
2277 * the caller's R0 isn't trashed.
2279 emitcode ("push", "psw");
2280 emitcode ("mov", "psw,#0x%02x",
2281 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2285 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2287 if (banksToSave & (1 << ix))
2289 saveRBank(ix, NULL, FALSE);
2293 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2298 /* if callee-save to be used for this function
2299 then save the registers being used in this function */
2300 if (sym->calleeSave)
2304 /* if any registers used */
2307 /* save the registers used */
2308 for (i = 0; i < sym->regsUsed->size; i++)
2310 if (bitVectBitValue (sym->regsUsed, i) ||
2311 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2313 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2321 /* set the register bank to the desired value */
2322 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2325 emitcode ("push", "psw");
2326 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2329 if (IS_RENT (sym->etype) || options.stackAuto)
2332 if (options.useXstack)
2334 emitcode ("mov", "r0,%s", spname);
2335 emitcode ("mov", "a,_bp");
2336 emitcode ("movx", "@r0,a");
2337 emitcode ("inc", "%s", spname);
2341 /* set up the stack */
2342 emitcode ("push", "_bp"); /* save the callers stack */
2344 emitcode ("mov", "_bp,%s", spname);
2347 /* adjust the stack for the function */
2353 werror (W_STACK_OVERFLOW, sym->name);
2355 if (i > 3 && sym->recvSize < 4)
2358 emitcode ("mov", "a,sp");
2359 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2360 emitcode ("mov", "sp,a");
2365 emitcode ("inc", "sp");
2371 emitcode ("mov", "a,_spx");
2372 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2373 emitcode ("mov", "_spx,a");
2378 /*-----------------------------------------------------------------*/
2379 /* genEndFunction - generates epilogue for functions */
2380 /*-----------------------------------------------------------------*/
2382 genEndFunction (iCode * ic)
2384 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2386 if (IS_RENT (sym->etype) || options.stackAuto)
2388 emitcode ("mov", "%s,_bp", spname);
2391 /* if use external stack but some variables were
2392 added to the local stack then decrement the
2394 if (options.useXstack && sym->stack)
2396 emitcode ("mov", "a,sp");
2397 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2398 emitcode ("mov", "sp,a");
2402 if ((IS_RENT (sym->etype) || options.stackAuto))
2404 if (options.useXstack)
2406 emitcode ("mov", "r0,%s", spname);
2407 emitcode ("movx", "a,@r0");
2408 emitcode ("mov", "_bp,a");
2409 emitcode ("dec", "%s", spname);
2413 emitcode ("pop", "_bp");
2417 /* restore the register bank */
2418 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2420 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2421 || !options.useXstack)
2423 /* Special case of ISR using non-zero bank with useXstack
2426 emitcode ("pop", "psw");
2430 if (IS_ISR (sym->etype))
2433 /* now we need to restore the registers */
2434 /* if this isr has no bank i.e. is going to
2435 run with bank 0 , then we need to save more
2437 if (!SPEC_BANK (sym->etype))
2439 /* if this function does not call any other
2440 function then we can be economical and
2441 save only those registers that are used */
2446 /* if any registers used */
2449 /* save the registers used */
2450 for (i = sym->regsUsed->size; i >= 0; i--)
2452 if (bitVectBitValue (sym->regsUsed, i) ||
2453 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2454 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2461 /* this function has a function call cannot
2462 determines register usage so we will have to pop the
2464 unsaveRBank (0, ic, FALSE);
2469 /* This ISR uses a non-zero bank.
2471 * Restore any register banks saved by genFunction
2474 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2477 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2479 if (savedBanks & (1 << ix))
2481 unsaveRBank(ix, NULL, FALSE);
2485 if (options.useXstack)
2487 /* Restore bank AFTER calling unsaveRBank,
2488 * since it can trash r0.
2490 emitcode ("pop", "psw");
2494 if (!inExcludeList ("dph"))
2495 emitcode ("pop", "dph");
2496 if (!inExcludeList ("dpl"))
2497 emitcode ("pop", "dpl");
2498 if (!inExcludeList ("b"))
2499 emitcode ("pop", "b");
2500 if (!inExcludeList ("acc"))
2501 emitcode ("pop", "acc");
2503 if (SPEC_CRTCL (sym->etype))
2504 emitcode ("setb", "ea");
2506 /* if debug then send end of function */
2507 /* if (options.debug && currFunc) { */
2511 emitcode ("", "C$%s$%d$%d$%d ==.",
2512 FileBaseName (ic->filename), currFunc->lastLine,
2513 ic->level, ic->block);
2514 if (IS_STATIC (currFunc->etype))
2515 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2517 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2521 emitcode ("reti", "");
2525 if (SPEC_CRTCL (sym->etype))
2526 emitcode ("setb", "ea");
2528 if (sym->calleeSave)
2532 /* if any registers used */
2535 /* save the registers used */
2536 for (i = sym->regsUsed->size; i >= 0; i--)
2538 if (bitVectBitValue (sym->regsUsed, i) ||
2539 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2540 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2546 /* if debug then send end of function */
2550 emitcode ("", "C$%s$%d$%d$%d ==.",
2551 FileBaseName (ic->filename), currFunc->lastLine,
2552 ic->level, ic->block);
2553 if (IS_STATIC (currFunc->etype))
2554 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2556 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2560 emitcode ("ret", "");
2565 /*-----------------------------------------------------------------*/
2566 /* genRet - generate code for return statement */
2567 /*-----------------------------------------------------------------*/
2571 int size, offset = 0, pushed = 0;
2573 /* if we have no return value then
2574 just generate the "ret" */
2578 /* we have something to return then
2579 move the return value into place */
2580 aopOp (IC_LEFT (ic), ic, FALSE);
2581 size = AOP_SIZE (IC_LEFT (ic));
2586 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2589 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2591 emitcode ("push", "%s", l);
2596 l = aopGet (AOP (IC_LEFT (ic)), offset,
2598 if (strcmp (fReturn[offset], l))
2599 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2608 if (strcmp (fReturn[pushed], "a"))
2609 emitcode ("pop", fReturn[pushed]);
2611 emitcode ("pop", "acc");
2614 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2617 /* generate a jump to the return label
2618 if the next is not the return statement */
2619 if (!(ic->next && ic->next->op == LABEL &&
2620 IC_LABEL (ic->next) == returnLabel))
2622 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2626 /*-----------------------------------------------------------------*/
2627 /* genLabel - generates a label */
2628 /*-----------------------------------------------------------------*/
2630 genLabel (iCode * ic)
2632 /* special case never generate */
2633 if (IC_LABEL (ic) == entryLabel)
2636 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2639 /*-----------------------------------------------------------------*/
2640 /* genGoto - generates a ljmp */
2641 /*-----------------------------------------------------------------*/
2643 genGoto (iCode * ic)
2645 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2648 /*-----------------------------------------------------------------*/
2649 /* findLabelBackwards: walks back through the iCode chain looking */
2650 /* for the given label. Returns number of iCode instructions */
2651 /* between that label and given ic. */
2652 /* Returns zero if label not found. */
2653 /*-----------------------------------------------------------------*/
2655 findLabelBackwards (iCode * ic, int key)
2664 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2666 /* printf("findLabelBackwards = %d\n", count); */
2674 /*-----------------------------------------------------------------*/
2675 /* genPlusIncr :- does addition with increment if possible */
2676 /*-----------------------------------------------------------------*/
2678 genPlusIncr (iCode * ic)
2680 unsigned int icount;
2681 unsigned int size = getDataSize (IC_RESULT (ic));
2683 /* will try to generate an increment */
2684 /* if the right side is not a literal
2686 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2689 /* if the literal value of the right hand side
2690 is greater than 4 then it is not worth it */
2691 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2694 /* if increment 16 bits in register */
2695 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2703 /* If the next instruction is a goto and the goto target
2704 * is < 10 instructions previous to this, we can generate
2705 * jumps straight to that target.
2707 if (ic->next && ic->next->op == GOTO
2708 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2709 && labelRange <= 10)
2711 emitcode (";", "tail increment optimized");
2712 tlbl = IC_LABEL (ic->next);
2717 tlbl = newiTempLabel (NULL);
2720 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2721 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2722 IS_AOP_PREG (IC_RESULT (ic)))
2723 emitcode ("cjne", "%s,#0x00,%05d$"
2724 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2728 emitcode ("clr", "a");
2729 emitcode ("cjne", "a,%s,%05d$"
2730 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2734 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2737 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2738 IS_AOP_PREG (IC_RESULT (ic)))
2739 emitcode ("cjne", "%s,#0x00,%05d$"
2740 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2743 emitcode ("cjne", "a,%s,%05d$"
2744 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2747 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2751 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2752 IS_AOP_PREG (IC_RESULT (ic)))
2753 emitcode ("cjne", "%s,#0x00,%05d$"
2754 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2758 emitcode ("cjne", "a,%s,%05d$"
2759 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2762 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2767 emitcode ("", "%05d$:", tlbl->key + 100);
2772 /* if the sizes are greater than 1 then we cannot */
2773 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2774 AOP_SIZE (IC_LEFT (ic)) > 1)
2777 /* we can if the aops of the left & result match or
2778 if they are in registers and the registers are the
2780 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2785 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2786 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2787 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2793 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2802 /*-----------------------------------------------------------------*/
2803 /* outBitAcc - output a bit in acc */
2804 /*-----------------------------------------------------------------*/
2806 outBitAcc (operand * result)
2808 symbol *tlbl = newiTempLabel (NULL);
2809 /* if the result is a bit */
2810 if (AOP_TYPE (result) == AOP_CRY)
2812 aopPut (AOP (result), "a", 0);
2816 emitcode ("jz", "%05d$", tlbl->key + 100);
2817 emitcode ("mov", "a,%s", one);
2818 emitcode ("", "%05d$:", tlbl->key + 100);
2823 /*-----------------------------------------------------------------*/
2824 /* genPlusBits - generates code for addition of two bits */
2825 /*-----------------------------------------------------------------*/
2827 genPlusBits (iCode * ic)
2829 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2831 symbol *lbl = newiTempLabel (NULL);
2832 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2833 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2834 emitcode ("cpl", "c");
2835 emitcode ("", "%05d$:", (lbl->key + 100));
2836 outBitC (IC_RESULT (ic));
2840 emitcode ("clr", "a");
2841 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2842 emitcode ("rlc", "a");
2843 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2844 emitcode ("addc", "a,#0x00");
2845 outAcc (IC_RESULT (ic));
2850 /* This is the original version of this code.
2852 * This is being kept around for reference,
2853 * because I am not entirely sure I got it right...
2856 adjustArithmeticResult (iCode * ic)
2858 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2859 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2860 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2861 aopPut (AOP (IC_RESULT (ic)),
2862 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2865 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2866 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2867 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2868 aopPut (AOP (IC_RESULT (ic)),
2869 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2872 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2873 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2874 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2875 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2876 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2879 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2880 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2884 /* This is the pure and virtuous version of this code.
2885 * I'm pretty certain it's right, but not enough to toss the old
2889 adjustArithmeticResult (iCode * ic)
2891 if (opIsGptr (IC_RESULT (ic)) &&
2892 opIsGptr (IC_LEFT (ic)) &&
2893 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2895 aopPut (AOP (IC_RESULT (ic)),
2896 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2900 if (opIsGptr (IC_RESULT (ic)) &&
2901 opIsGptr (IC_RIGHT (ic)) &&
2902 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2904 aopPut (AOP (IC_RESULT (ic)),
2905 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2909 if (opIsGptr (IC_RESULT (ic)) &&
2910 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2911 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2912 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2913 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2916 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2917 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2922 /*-----------------------------------------------------------------*/
2923 /* genPlus - generates code for addition */
2924 /*-----------------------------------------------------------------*/
2926 genPlus (iCode * ic)
2928 int size, offset = 0;
2930 /* special cases :- */
2932 aopOp (IC_LEFT (ic), ic, FALSE);
2933 aopOp (IC_RIGHT (ic), ic, FALSE);
2934 aopOp (IC_RESULT (ic), ic, TRUE);
2936 /* if literal, literal on the right or
2937 if left requires ACC or right is already
2939 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2940 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2941 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2943 operand *t = IC_RIGHT (ic);
2944 IC_RIGHT (ic) = IC_LEFT (ic);
2948 /* if both left & right are in bit
2950 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2951 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2957 /* if left in bit space & right literal */
2958 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2959 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2961 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2962 /* if result in bit space */
2963 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2965 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2966 emitcode ("cpl", "c");
2967 outBitC (IC_RESULT (ic));
2971 size = getDataSize (IC_RESULT (ic));
2974 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2975 emitcode ("addc", "a,#00");
2976 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2982 /* if I can do an increment instead
2983 of add then GOOD for ME */
2984 if (genPlusIncr (ic) == TRUE)
2987 size = getDataSize (IC_RESULT (ic));
2991 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2993 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2995 emitcode ("add", "a,%s",
2996 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2998 emitcode ("addc", "a,%s",
2999 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3003 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3005 emitcode ("add", "a,%s",
3006 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3008 emitcode ("addc", "a,%s",
3009 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3011 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3014 adjustArithmeticResult (ic);
3017 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3018 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3022 /*-----------------------------------------------------------------*/
3023 /* genMinusDec :- does subtraction with deccrement if possible */
3024 /*-----------------------------------------------------------------*/
3026 genMinusDec (iCode * ic)
3028 unsigned int icount;
3029 unsigned int size = getDataSize (IC_RESULT (ic));
3031 /* will try to generate an increment */
3032 /* if the right side is not a literal
3034 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3037 /* if the literal value of the right hand side
3038 is greater than 4 then it is not worth it */
3039 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3042 /* if decrement 16 bits in register */
3043 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3051 /* If the next instruction is a goto and the goto target
3052 * is <= 10 instructions previous to this, we can generate
3053 * jumps straight to that target.
3055 if (ic->next && ic->next->op == GOTO
3056 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3057 && labelRange <= 10)
3059 emitcode (";", "tail decrement optimized");
3060 tlbl = IC_LABEL (ic->next);
3065 tlbl = newiTempLabel (NULL);
3069 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3070 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3071 IS_AOP_PREG (IC_RESULT (ic)))
3072 emitcode ("cjne", "%s,#0xff,%05d$"
3073 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3077 emitcode ("mov", "a,#0xff");
3078 emitcode ("cjne", "a,%s,%05d$"
3079 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3082 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3085 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3086 IS_AOP_PREG (IC_RESULT (ic)))
3087 emitcode ("cjne", "%s,#0xff,%05d$"
3088 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3092 emitcode ("cjne", "a,%s,%05d$"
3093 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3096 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3100 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3101 IS_AOP_PREG (IC_RESULT (ic)))
3102 emitcode ("cjne", "%s,#0xff,%05d$"
3103 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3107 emitcode ("cjne", "a,%s,%05d$"
3108 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3111 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3115 emitcode ("", "%05d$:", tlbl->key + 100);
3120 /* if the sizes are greater than 1 then we cannot */
3121 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3122 AOP_SIZE (IC_LEFT (ic)) > 1)
3125 /* we can if the aops of the left & result match or
3126 if they are in registers and the registers are the
3128 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3132 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3140 /*-----------------------------------------------------------------*/
3141 /* addSign - complete with sign */
3142 /*-----------------------------------------------------------------*/
3144 addSign (operand * result, int offset, int sign)
3146 int size = (getDataSize (result) - offset);
3151 emitcode ("rlc", "a");
3152 emitcode ("subb", "a,acc");
3154 aopPut (AOP (result), "a", offset++);
3158 aopPut (AOP (result), zero, offset++);
3162 /*-----------------------------------------------------------------*/
3163 /* genMinusBits - generates code for subtraction of two bits */
3164 /*-----------------------------------------------------------------*/
3166 genMinusBits (iCode * ic)
3168 symbol *lbl = newiTempLabel (NULL);
3169 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3171 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3172 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3173 emitcode ("cpl", "c");
3174 emitcode ("", "%05d$:", (lbl->key + 100));
3175 outBitC (IC_RESULT (ic));
3179 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3180 emitcode ("subb", "a,acc");
3181 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3182 emitcode ("inc", "a");
3183 emitcode ("", "%05d$:", (lbl->key + 100));
3184 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3185 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3189 /*-----------------------------------------------------------------*/
3190 /* genMinus - generates code for subtraction */
3191 /*-----------------------------------------------------------------*/
3193 genMinus (iCode * ic)
3195 int size, offset = 0;
3196 unsigned long lit = 0L;
3198 aopOp (IC_LEFT (ic), ic, FALSE);
3199 aopOp (IC_RIGHT (ic), ic, FALSE);
3200 aopOp (IC_RESULT (ic), ic, TRUE);
3202 /* special cases :- */
3203 /* if both left & right are in bit space */
3204 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3205 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3211 /* if I can do an decrement instead
3212 of subtract then GOOD for ME */
3213 if (genMinusDec (ic) == TRUE)
3216 size = getDataSize (IC_RESULT (ic));
3218 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3224 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3228 /* if literal, add a,#-lit, else normal subb */
3231 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3232 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3233 emitcode ("subb", "a,%s",
3234 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3237 /* first add without previous c */
3239 emitcode ("add", "a,#0x%02x",
3240 (unsigned int) (lit & 0x0FFL));
3242 emitcode ("addc", "a,#0x%02x",
3243 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3245 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3248 adjustArithmeticResult (ic);
3251 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3252 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3257 /*-----------------------------------------------------------------*/
3258 /* genMultbits :- multiplication of bits */
3259 /*-----------------------------------------------------------------*/
3261 genMultbits (operand * left,
3265 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3266 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3271 /*-----------------------------------------------------------------*/
3272 /* genMultOneByte : 8*8=8/16 bit multiplication */
3273 /*-----------------------------------------------------------------*/
3275 genMultOneByte (operand * left,
3279 sym_link *opetype = operandType (result);
3281 int size=AOP_SIZE(result);
3283 //emitcode (";",__FUNCTION__);
3284 if (size<1 || size>2) {
3285 // this should never happen
3286 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3287 AOP_SIZE(result), __FILE__, lineno);
3291 /* (if two literals: the value is computed before) */
3292 /* if one literal, literal on the right */
3293 if (AOP_TYPE (left) == AOP_LIT)
3298 //emitcode (";", "swapped left and right");
3301 if (SPEC_USIGN(opetype)
3302 // ignore the sign of left and right, what else can we do?
3303 || (SPEC_USIGN(operandType(left)) &&
3304 SPEC_USIGN(operandType(right)))) {
3305 // just an unsigned 8*8=8/16 multiply
3306 //emitcode (";","unsigned");
3307 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3308 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3309 emitcode ("mul", "ab");
3310 aopPut (AOP (result), "a", 0);
3312 aopPut (AOP (result), "b", 1);
3317 // we have to do a signed multiply
3319 //emitcode (";", "signed");
3320 emitcode ("clr", "F0"); // reset sign flag
3321 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3322 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3324 lbl=newiTempLabel(NULL);
3325 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3326 // left side is negative, 8-bit two's complement, this fails for -128
3327 emitcode ("setb", "F0"); // set sign flag
3328 emitcode ("cpl", "a");
3329 emitcode ("inc", "a");
3331 emitcode ("", "%05d$:", lbl->key+100);
3332 emitcode ("xch", "a,b");
3335 if (AOP_TYPE(right)==AOP_LIT) {
3336 /* AND literal negative */
3337 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3338 // two's complement for literal<0
3339 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3340 emitcode ("cpl", "a");
3341 emitcode ("inc", "a");
3344 lbl=newiTempLabel(NULL);
3345 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3346 // right side is negative, 8-bit two's complement
3347 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3348 emitcode ("cpl", "a");
3349 emitcode ("inc", "a");
3350 emitcode ("", "%05d$:", lbl->key+100);
3352 emitcode ("mul", "ab");
3354 lbl=newiTempLabel(NULL);
3355 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3356 // only ONE op was negative, we have to do a 8/16-bit two's complement
3357 emitcode ("cpl", "a"); // lsb
3359 emitcode ("inc", "a");
3361 emitcode ("add", "a,#1");
3362 emitcode ("xch", "a,b");
3363 emitcode ("cpl", "a"); // msb
3364 emitcode ("addc", "a,#0");
3365 emitcode ("xch", "a,b");
3368 emitcode ("", "%05d$:", lbl->key+100);
3369 aopPut (AOP (result), "a", 0);
3371 aopPut (AOP (result), "b", 1);
3375 /*-----------------------------------------------------------------*/
3376 /* genMult - generates code for multiplication */
3377 /*-----------------------------------------------------------------*/
3379 genMult (iCode * ic)
3381 operand *left = IC_LEFT (ic);
3382 operand *right = IC_RIGHT (ic);
3383 operand *result = IC_RESULT (ic);
3385 /* assign the amsops */
3386 aopOp (left, ic, FALSE);
3387 aopOp (right, ic, FALSE);
3388 aopOp (result, ic, TRUE);
3390 /* special cases first */
3392 if (AOP_TYPE (left) == AOP_CRY &&
3393 AOP_TYPE (right) == AOP_CRY)
3395 genMultbits (left, right, result);
3399 /* if both are of size == 1 */
3400 if (AOP_SIZE (left) == 1 &&
3401 AOP_SIZE (right) == 1)
3403 genMultOneByte (left, right, result);
3407 /* should have been converted to function call */
3411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3412 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3413 freeAsmop (result, NULL, ic, TRUE);
3416 /*-----------------------------------------------------------------*/
3417 /* genDivbits :- division of bits */
3418 /*-----------------------------------------------------------------*/
3420 genDivbits (operand * left,
3427 /* the result must be bit */
3428 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3429 l = aopGet (AOP (left), 0, FALSE, FALSE);
3433 emitcode ("div", "ab");
3434 emitcode ("rrc", "a");
3435 aopPut (AOP (result), "c", 0);
3438 /*-----------------------------------------------------------------*/
3439 /* genDivOneByte : 8 bit division */
3440 /*-----------------------------------------------------------------*/
3442 genDivOneByte (operand * left,
3446 sym_link *opetype = operandType (result);
3451 size = AOP_SIZE (result) - 1;
3453 /* signed or unsigned */
3454 if (SPEC_USIGN (opetype))
3456 /* unsigned is easy */
3457 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3458 l = aopGet (AOP (left), 0, FALSE, FALSE);
3460 emitcode ("div", "ab");
3461 aopPut (AOP (result), "a", 0);
3463 aopPut (AOP (result), zero, offset++);
3467 /* signed is a little bit more difficult */
3469 /* save the signs of the operands */
3470 l = aopGet (AOP (left), 0, FALSE, FALSE);
3472 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3473 emitcode ("push", "acc"); /* save it on the stack */
3475 /* now sign adjust for both left & right */
3476 l = aopGet (AOP (right), 0, FALSE, FALSE);
3478 lbl = newiTempLabel (NULL);
3479 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3480 emitcode ("cpl", "a");
3481 emitcode ("inc", "a");
3482 emitcode ("", "%05d$:", (lbl->key + 100));
3483 emitcode ("mov", "b,a");
3485 /* sign adjust left side */
3486 l = aopGet (AOP (left), 0, FALSE, FALSE);
3489 lbl = newiTempLabel (NULL);
3490 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3491 emitcode ("cpl", "a");
3492 emitcode ("inc", "a");
3493 emitcode ("", "%05d$:", (lbl->key + 100));
3495 /* now the division */
3496 emitcode ("div", "ab");
3497 /* we are interested in the lower order
3499 emitcode ("mov", "b,a");
3500 lbl = newiTempLabel (NULL);
3501 emitcode ("pop", "acc");
3502 /* if there was an over flow we don't
3503 adjust the sign of the result */
3504 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3505 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3507 emitcode ("clr", "a");
3508 emitcode ("subb", "a,b");
3509 emitcode ("mov", "b,a");
3510 emitcode ("", "%05d$:", (lbl->key + 100));
3512 /* now we are done */
3513 aopPut (AOP (result), "b", 0);
3516 emitcode ("mov", "c,b.7");
3517 emitcode ("subb", "a,acc");
3520 aopPut (AOP (result), "a", offset++);
3524 /*-----------------------------------------------------------------*/
3525 /* genDiv - generates code for division */
3526 /*-----------------------------------------------------------------*/
3530 operand *left = IC_LEFT (ic);
3531 operand *right = IC_RIGHT (ic);
3532 operand *result = IC_RESULT (ic);
3534 /* assign the amsops */
3535 aopOp (left, ic, FALSE);
3536 aopOp (right, ic, FALSE);
3537 aopOp (result, ic, TRUE);
3539 /* special cases first */
3541 if (AOP_TYPE (left) == AOP_CRY &&
3542 AOP_TYPE (right) == AOP_CRY)
3544 genDivbits (left, right, result);
3548 /* if both are of size == 1 */
3549 if (AOP_SIZE (left) == 1 &&
3550 AOP_SIZE (right) == 1)
3552 genDivOneByte (left, right, result);
3556 /* should have been converted to function call */
3559 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3560 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3561 freeAsmop (result, NULL, ic, TRUE);
3564 /*-----------------------------------------------------------------*/
3565 /* genModbits :- modulus of bits */
3566 /*-----------------------------------------------------------------*/
3568 genModbits (operand * left,
3575 /* the result must be bit */
3576 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3577 l = aopGet (AOP (left), 0, FALSE, FALSE);
3581 emitcode ("div", "ab");
3582 emitcode ("mov", "a,b");
3583 emitcode ("rrc", "a");
3584 aopPut (AOP (result), "c", 0);
3587 /*-----------------------------------------------------------------*/
3588 /* genModOneByte : 8 bit modulus */
3589 /*-----------------------------------------------------------------*/
3591 genModOneByte (operand * left,
3595 sym_link *opetype = operandType (result);
3599 /* signed or unsigned */
3600 if (SPEC_USIGN (opetype))
3602 /* unsigned is easy */
3603 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3604 l = aopGet (AOP (left), 0, FALSE, FALSE);
3606 emitcode ("div", "ab");
3607 aopPut (AOP (result), "b", 0);
3611 /* signed is a little bit more difficult */
3613 /* save the signs of the operands */
3614 l = aopGet (AOP (left), 0, FALSE, FALSE);
3617 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3618 emitcode ("push", "acc"); /* save it on the stack */
3620 /* now sign adjust for both left & right */
3621 l = aopGet (AOP (right), 0, FALSE, FALSE);
3624 lbl = newiTempLabel (NULL);
3625 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3626 emitcode ("cpl", "a");
3627 emitcode ("inc", "a");
3628 emitcode ("", "%05d$:", (lbl->key + 100));
3629 emitcode ("mov", "b,a");
3631 /* sign adjust left side */
3632 l = aopGet (AOP (left), 0, FALSE, FALSE);
3635 lbl = newiTempLabel (NULL);
3636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3637 emitcode ("cpl", "a");
3638 emitcode ("inc", "a");
3639 emitcode ("", "%05d$:", (lbl->key + 100));
3641 /* now the multiplication */
3642 emitcode ("div", "ab");
3643 /* we are interested in the lower order
3645 lbl = newiTempLabel (NULL);
3646 emitcode ("pop", "acc");
3647 /* if there was an over flow we don't
3648 adjust the sign of the result */
3649 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3650 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3652 emitcode ("clr", "a");
3653 emitcode ("subb", "a,b");
3654 emitcode ("mov", "b,a");
3655 emitcode ("", "%05d$:", (lbl->key + 100));
3657 /* now we are done */
3658 aopPut (AOP (result), "b", 0);
3662 /*-----------------------------------------------------------------*/
3663 /* genMod - generates code for division */
3664 /*-----------------------------------------------------------------*/
3668 operand *left = IC_LEFT (ic);
3669 operand *right = IC_RIGHT (ic);
3670 operand *result = IC_RESULT (ic);
3672 /* assign the amsops */
3673 aopOp (left, ic, FALSE);
3674 aopOp (right, ic, FALSE);
3675 aopOp (result, ic, TRUE);
3677 /* special cases first */
3679 if (AOP_TYPE (left) == AOP_CRY &&
3680 AOP_TYPE (right) == AOP_CRY)
3682 genModbits (left, right, result);
3686 /* if both are of size == 1 */
3687 if (AOP_SIZE (left) == 1 &&
3688 AOP_SIZE (right) == 1)
3690 genModOneByte (left, right, result);
3694 /* should have been converted to function call */
3698 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3699 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3700 freeAsmop (result, NULL, ic, TRUE);
3703 /*-----------------------------------------------------------------*/
3704 /* genIfxJump :- will create a jump depending on the ifx */
3705 /*-----------------------------------------------------------------*/
3707 genIfxJump (iCode * ic, char *jval)
3710 symbol *tlbl = newiTempLabel (NULL);
3713 /* if true label then we jump if condition
3717 jlbl = IC_TRUE (ic);
3718 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3719 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3723 /* false label is present */
3724 jlbl = IC_FALSE (ic);
3725 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3726 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3728 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3729 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3731 emitcode (inst, "%05d$", tlbl->key + 100);
3732 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3733 emitcode ("", "%05d$:", tlbl->key + 100);
3735 /* mark the icode as generated */
3739 /*-----------------------------------------------------------------*/
3740 /* genCmp :- greater or less than comparison */
3741 /*-----------------------------------------------------------------*/
3743 genCmp (operand * left, operand * right,
3744 operand * result, iCode * ifx, int sign, iCode *ic)
3746 int size, offset = 0;
3747 unsigned long lit = 0L;
3749 /* if left & right are bit variables */
3750 if (AOP_TYPE (left) == AOP_CRY &&
3751 AOP_TYPE (right) == AOP_CRY)
3753 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3754 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3758 /* subtract right from left if at the
3759 end the carry flag is set then we know that
3760 left is greater than right */
3761 size = max (AOP_SIZE (left), AOP_SIZE (right));
3763 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3764 if ((size == 1) && !sign &&
3765 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3767 symbol *lbl = newiTempLabel (NULL);
3768 emitcode ("cjne", "%s,%s,%05d$",
3769 aopGet (AOP (left), offset, FALSE, FALSE),
3770 aopGet (AOP (right), offset, FALSE, FALSE),
3772 emitcode ("", "%05d$:", lbl->key + 100);
3776 if (AOP_TYPE (right) == AOP_LIT)
3778 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3779 /* optimize if(x < 0) or if(x >= 0) */
3788 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3789 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3791 genIfxJump (ifx, "acc.7");
3795 emitcode ("rlc", "a");
3803 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3804 if (sign && size == 0)
3806 emitcode ("xrl", "a,#0x80");
3807 if (AOP_TYPE (right) == AOP_LIT)
3809 unsigned long lit = (unsigned long)
3810 floatFromVal (AOP (right)->aopu.aop_lit);
3811 emitcode ("subb", "a,#0x%02x",
3812 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3816 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3817 emitcode ("xrl", "b,#0x80");
3818 emitcode ("subb", "a,b");
3822 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3836 /* if the result is used in the next
3837 ifx conditional branch then generate
3838 code a little differently */
3840 genIfxJump (ifx, "c");
3843 /* leave the result in acc */
3847 /*-----------------------------------------------------------------*/
3848 /* genCmpGt :- greater than comparison */
3849 /*-----------------------------------------------------------------*/
3851 genCmpGt (iCode * ic, iCode * ifx)
3853 operand *left, *right, *result;
3854 sym_link *letype, *retype;
3857 left = IC_LEFT (ic);
3858 right = IC_RIGHT (ic);
3859 result = IC_RESULT (ic);
3861 letype = getSpec (operandType (left));
3862 retype = getSpec (operandType (right));
3863 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3864 /* assign the amsops */
3865 aopOp (left, ic, FALSE);
3866 aopOp (right, ic, FALSE);
3867 aopOp (result, ic, TRUE);
3869 genCmp (right, left, result, ifx, sign,ic);
3871 freeAsmop (result, NULL, ic, TRUE);
3874 /*-----------------------------------------------------------------*/
3875 /* genCmpLt - less than comparisons */
3876 /*-----------------------------------------------------------------*/
3878 genCmpLt (iCode * ic, iCode * ifx)
3880 operand *left, *right, *result;
3881 sym_link *letype, *retype;
3884 left = IC_LEFT (ic);
3885 right = IC_RIGHT (ic);
3886 result = IC_RESULT (ic);
3888 letype = getSpec (operandType (left));
3889 retype = getSpec (operandType (right));
3890 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3892 /* assign the amsops */
3893 aopOp (left, ic, FALSE);
3894 aopOp (right, ic, FALSE);
3895 aopOp (result, ic, TRUE);
3897 genCmp (left, right, result, ifx, sign,ic);
3899 freeAsmop (result, NULL, ic, TRUE);
3902 /*-----------------------------------------------------------------*/
3903 /* gencjneshort - compare and jump if not equal */
3904 /*-----------------------------------------------------------------*/
3906 gencjneshort (operand * left, operand * right, symbol * lbl)
3908 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3910 unsigned long lit = 0L;
3912 /* if the left side is a literal or
3913 if the right is in a pointer register and left
3915 if ((AOP_TYPE (left) == AOP_LIT) ||
3916 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3922 if (AOP_TYPE (right) == AOP_LIT)
3923 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3925 /* if the right side is a literal then anything goes */
3926 if (AOP_TYPE (right) == AOP_LIT &&
3927 AOP_TYPE (left) != AOP_DIR)
3931 emitcode ("cjne", "%s,%s,%05d$",
3932 aopGet (AOP (left), offset, FALSE, FALSE),
3933 aopGet (AOP (right), offset, FALSE, FALSE),
3939 /* if the right side is in a register or in direct space or
3940 if the left is a pointer register & right is not */
3941 else if (AOP_TYPE (right) == AOP_REG ||
3942 AOP_TYPE (right) == AOP_DIR ||
3943 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3944 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3948 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3949 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3950 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3951 emitcode ("jnz", "%05d$", lbl->key + 100);
3953 emitcode ("cjne", "a,%s,%05d$",
3954 aopGet (AOP (right), offset, FALSE, TRUE),
3961 /* right is a pointer reg need both a & b */
3964 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3965 if (strcmp (l, "b"))
3966 emitcode ("mov", "b,%s", l);
3967 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3968 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3974 /*-----------------------------------------------------------------*/
3975 /* gencjne - compare and jump if not equal */
3976 /*-----------------------------------------------------------------*/
3978 gencjne (operand * left, operand * right, symbol * lbl)
3980 symbol *tlbl = newiTempLabel (NULL);
3982 gencjneshort (left, right, lbl);
3984 emitcode ("mov", "a,%s", one);
3985 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3986 emitcode ("", "%05d$:", lbl->key + 100);
3987 emitcode ("clr", "a");
3988 emitcode ("", "%05d$:", tlbl->key + 100);
3991 /*-----------------------------------------------------------------*/
3992 /* genCmpEq - generates code for equal to */
3993 /*-----------------------------------------------------------------*/
3995 genCmpEq (iCode * ic, iCode * ifx)
3997 operand *left, *right, *result;
3999 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4000 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4001 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4003 /* if literal, literal on the right or
4004 if the right is in a pointer register and left
4006 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4007 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4009 operand *t = IC_RIGHT (ic);
4010 IC_RIGHT (ic) = IC_LEFT (ic);
4014 if (ifx && !AOP_SIZE (result))
4017 /* if they are both bit variables */
4018 if (AOP_TYPE (left) == AOP_CRY &&
4019 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4021 if (AOP_TYPE (right) == AOP_LIT)
4023 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4026 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4027 emitcode ("cpl", "c");
4031 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4035 emitcode ("clr", "c");
4037 /* AOP_TYPE(right) == AOP_CRY */
4041 symbol *lbl = newiTempLabel (NULL);
4042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4043 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4044 emitcode ("cpl", "c");
4045 emitcode ("", "%05d$:", (lbl->key + 100));
4047 /* if true label then we jump if condition
4049 tlbl = newiTempLabel (NULL);
4052 emitcode ("jnc", "%05d$", tlbl->key + 100);
4053 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4057 emitcode ("jc", "%05d$", tlbl->key + 100);
4058 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4060 emitcode ("", "%05d$:", tlbl->key + 100);
4064 tlbl = newiTempLabel (NULL);
4065 gencjneshort (left, right, tlbl);
4068 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4069 emitcode ("", "%05d$:", tlbl->key + 100);
4073 symbol *lbl = newiTempLabel (NULL);
4074 emitcode ("sjmp", "%05d$", lbl->key + 100);
4075 emitcode ("", "%05d$:", tlbl->key + 100);
4076 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4077 emitcode ("", "%05d$:", lbl->key + 100);
4080 /* mark the icode as generated */
4085 /* if they are both bit variables */
4086 if (AOP_TYPE (left) == AOP_CRY &&
4087 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4089 if (AOP_TYPE (right) == AOP_LIT)
4091 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4094 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4095 emitcode ("cpl", "c");
4099 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4103 emitcode ("clr", "c");
4105 /* AOP_TYPE(right) == AOP_CRY */
4109 symbol *lbl = newiTempLabel (NULL);
4110 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4111 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4112 emitcode ("cpl", "c");
4113 emitcode ("", "%05d$:", (lbl->key + 100));
4116 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4123 genIfxJump (ifx, "c");
4126 /* if the result is used in an arithmetic operation
4127 then put the result in place */
4132 gencjne (left, right, newiTempLabel (NULL));
4133 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4135 aopPut (AOP (result), "a", 0);
4140 genIfxJump (ifx, "a");
4143 /* if the result is used in an arithmetic operation
4144 then put the result in place */
4145 if (AOP_TYPE (result) != AOP_CRY)
4147 /* leave the result in acc */
4151 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4153 freeAsmop (result, NULL, ic, TRUE);
4156 /*-----------------------------------------------------------------*/
4157 /* ifxForOp - returns the icode containing the ifx for operand */
4158 /*-----------------------------------------------------------------*/
4160 ifxForOp (operand * op, iCode * ic)
4162 /* if true symbol then needs to be assigned */
4163 if (IS_TRUE_SYMOP (op))
4166 /* if this has register type condition and
4167 the next instruction is ifx with the same operand
4168 and live to of the operand is upto the ifx only then */
4170 ic->next->op == IFX &&
4171 IC_COND (ic->next)->key == op->key &&
4172 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4178 /*-----------------------------------------------------------------*/
4179 /* hasInc - operand is incremented before any other use */
4180 /*-----------------------------------------------------------------*/
4182 hasInc (operand *op, iCode *ic)
4184 sym_link *type = operandType(op);
4185 sym_link *retype = getSpec (type);
4186 iCode *lic = ic->next;
4189 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4190 isize = getSize(type->next);
4192 /* if operand of the form op = op + <sizeof *op> */
4193 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4194 isOperandEqual(IC_RESULT(lic),op) &&
4195 isOperandLiteral(IC_RIGHT(lic)) &&
4196 operandLitValue(IC_RIGHT(lic)) == isize) {
4199 /* if the operand used or deffed */
4200 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4208 /*-----------------------------------------------------------------*/
4209 /* genAndOp - for && operation */
4210 /*-----------------------------------------------------------------*/
4212 genAndOp (iCode * ic)
4214 operand *left, *right, *result;
4217 /* note here that && operations that are in an
4218 if statement are taken away by backPatchLabels
4219 only those used in arthmetic operations remain */
4220 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4221 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4222 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4224 /* if both are bit variables */
4225 if (AOP_TYPE (left) == AOP_CRY &&
4226 AOP_TYPE (right) == AOP_CRY)
4228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4229 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4234 tlbl = newiTempLabel (NULL);
4236 emitcode ("jz", "%05d$", tlbl->key + 100);
4238 emitcode ("", "%05d$:", tlbl->key + 100);
4242 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4243 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4244 freeAsmop (result, NULL, ic, TRUE);
4248 /*-----------------------------------------------------------------*/
4249 /* genOrOp - for || operation */
4250 /*-----------------------------------------------------------------*/
4252 genOrOp (iCode * ic)
4254 operand *left, *right, *result;
4257 /* note here that || operations that are in an
4258 if statement are taken away by backPatchLabels
4259 only those used in arthmetic operations remain */
4260 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4261 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4262 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4264 /* if both are bit variables */
4265 if (AOP_TYPE (left) == AOP_CRY &&
4266 AOP_TYPE (right) == AOP_CRY)
4268 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4269 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4274 tlbl = newiTempLabel (NULL);
4276 emitcode ("jnz", "%05d$", tlbl->key + 100);
4278 emitcode ("", "%05d$:", tlbl->key + 100);
4282 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4283 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4284 freeAsmop (result, NULL, ic, TRUE);
4287 /*-----------------------------------------------------------------*/
4288 /* isLiteralBit - test if lit == 2^n */
4289 /*-----------------------------------------------------------------*/
4291 isLiteralBit (unsigned long lit)
4293 unsigned long pw[32] =
4294 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4295 0x100L, 0x200L, 0x400L, 0x800L,
4296 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4297 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4298 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4299 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4300 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4303 for (idx = 0; idx < 32; idx++)
4309 /*-----------------------------------------------------------------*/
4310 /* continueIfTrue - */
4311 /*-----------------------------------------------------------------*/
4313 continueIfTrue (iCode * ic)
4316 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4320 /*-----------------------------------------------------------------*/
4322 /*-----------------------------------------------------------------*/
4324 jumpIfTrue (iCode * ic)
4327 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4331 /*-----------------------------------------------------------------*/
4332 /* jmpTrueOrFalse - */
4333 /*-----------------------------------------------------------------*/
4335 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4337 // ugly but optimized by peephole
4340 symbol *nlbl = newiTempLabel (NULL);
4341 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4342 emitcode ("", "%05d$:", tlbl->key + 100);
4343 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4344 emitcode ("", "%05d$:", nlbl->key + 100);
4348 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4349 emitcode ("", "%05d$:", tlbl->key + 100);
4354 /*-----------------------------------------------------------------*/
4355 /* genAnd - code for and */
4356 /*-----------------------------------------------------------------*/
4358 genAnd (iCode * ic, iCode * ifx)
4360 operand *left, *right, *result;
4361 int size, offset = 0;
4362 unsigned long lit = 0L;
4366 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4367 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4368 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4371 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4373 AOP_TYPE (left), AOP_TYPE (right));
4374 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4376 AOP_SIZE (left), AOP_SIZE (right));
4379 /* if left is a literal & right is not then exchange them */
4380 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4381 AOP_NEEDSACC (left))
4383 operand *tmp = right;
4388 /* if result = right then exchange them */
4389 if (sameRegs (AOP (result), AOP (right)))
4391 operand *tmp = right;
4396 /* if right is bit then exchange them */
4397 if (AOP_TYPE (right) == AOP_CRY &&
4398 AOP_TYPE (left) != AOP_CRY)
4400 operand *tmp = right;
4404 if (AOP_TYPE (right) == AOP_LIT)
4405 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4407 size = AOP_SIZE (result);
4410 // result = bit & yy;
4411 if (AOP_TYPE (left) == AOP_CRY)
4413 // c = bit & literal;
4414 if (AOP_TYPE (right) == AOP_LIT)
4418 if (size && sameRegs (AOP (result), AOP (left)))
4421 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4426 if (size && (AOP_TYPE (result) == AOP_CRY))
4428 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4431 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4436 emitcode ("clr", "c");
4441 if (AOP_TYPE (right) == AOP_CRY)
4444 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4445 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4450 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4452 emitcode ("rrc", "a");
4453 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4461 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4462 genIfxJump (ifx, "c");
4466 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4467 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4468 if ((AOP_TYPE (right) == AOP_LIT) &&
4469 (AOP_TYPE (result) == AOP_CRY) &&
4470 (AOP_TYPE (left) != AOP_CRY))
4472 int posbit = isLiteralBit (lit);
4477 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4480 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4486 sprintf (buffer, "acc.%d", posbit & 0x07);
4487 genIfxJump (ifx, buffer);
4494 symbol *tlbl = newiTempLabel (NULL);
4495 int sizel = AOP_SIZE (left);
4497 emitcode ("setb", "c");
4500 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4502 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4504 if ((posbit = isLiteralBit (bytelit)) != 0)
4505 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4508 if (bytelit != 0x0FFL)
4509 emitcode ("anl", "a,%s",
4510 aopGet (AOP (right), offset, FALSE, TRUE));
4511 emitcode ("jnz", "%05d$", tlbl->key + 100);
4516 // bit = left & literal
4519 emitcode ("clr", "c");
4520 emitcode ("", "%05d$:", tlbl->key + 100);
4522 // if(left & literal)
4526 jmpTrueOrFalse (ifx, tlbl);
4534 /* if left is same as result */
4535 if (sameRegs (AOP (result), AOP (left)))
4537 for (; size--; offset++)
4539 if (AOP_TYPE (right) == AOP_LIT)
4541 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4543 else if (bytelit == 0)
4544 aopPut (AOP (result), zero, offset);
4545 else if (IS_AOP_PREG (result))
4547 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4548 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4549 aopPut (AOP (result), "a", offset);
4552 emitcode ("anl", "%s,%s",
4553 aopGet (AOP (left), offset, FALSE, TRUE),
4554 aopGet (AOP (right), offset, FALSE, FALSE));
4558 if (AOP_TYPE (left) == AOP_ACC)
4559 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4562 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4563 if (IS_AOP_PREG (result))
4565 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4566 aopPut (AOP (result), "a", offset);
4570 emitcode ("anl", "%s,a",
4571 aopGet (AOP (left), offset, FALSE, TRUE));
4578 // left & result in different registers
4579 if (AOP_TYPE (result) == AOP_CRY)
4582 // if(size), result in bit
4583 // if(!size && ifx), conditional oper: if(left & right)
4584 symbol *tlbl = newiTempLabel (NULL);
4585 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4587 emitcode ("setb", "c");
4590 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4591 emitcode ("anl", "a,%s",
4592 aopGet (AOP (left), offset, FALSE, FALSE));
4593 emitcode ("jnz", "%05d$", tlbl->key + 100);
4599 emitcode ("", "%05d$:", tlbl->key + 100);
4603 jmpTrueOrFalse (ifx, tlbl);
4607 for (; (size--); offset++)
4610 // result = left & right
4611 if (AOP_TYPE (right) == AOP_LIT)
4613 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4615 aopPut (AOP (result),
4616 aopGet (AOP (left), offset, FALSE, FALSE),
4620 else if (bytelit == 0)
4622 aopPut (AOP (result), zero, offset);
4626 // faster than result <- left, anl result,right
4627 // and better if result is SFR
4628 if (AOP_TYPE (left) == AOP_ACC)
4629 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4633 emitcode ("anl", "a,%s",
4634 aopGet (AOP (left), offset, FALSE, FALSE));
4636 aopPut (AOP (result), "a", offset);
4642 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4644 freeAsmop (result, NULL, ic, TRUE);
4647 /*-----------------------------------------------------------------*/
4648 /* genOr - code for or */
4649 /*-----------------------------------------------------------------*/
4651 genOr (iCode * ic, iCode * ifx)
4653 operand *left, *right, *result;
4654 int size, offset = 0;
4655 unsigned long lit = 0L;
4657 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4658 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4659 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4662 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4664 AOP_TYPE (left), AOP_TYPE (right));
4665 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4667 AOP_SIZE (left), AOP_SIZE (right));
4670 /* if left is a literal & right is not then exchange them */
4671 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4672 AOP_NEEDSACC (left))
4674 operand *tmp = right;
4679 /* if result = right then exchange them */
4680 if (sameRegs (AOP (result), AOP (right)))
4682 operand *tmp = right;
4687 /* if right is bit then exchange them */
4688 if (AOP_TYPE (right) == AOP_CRY &&
4689 AOP_TYPE (left) != AOP_CRY)
4691 operand *tmp = right;
4695 if (AOP_TYPE (right) == AOP_LIT)
4696 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4698 size = AOP_SIZE (result);
4702 if (AOP_TYPE (left) == AOP_CRY)
4704 if (AOP_TYPE (right) == AOP_LIT)
4706 // c = bit & literal;
4709 // lit != 0 => result = 1
4710 if (AOP_TYPE (result) == AOP_CRY)
4713 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4715 continueIfTrue (ifx);
4718 emitcode ("setb", "c");
4722 // lit == 0 => result = left
4723 if (size && sameRegs (AOP (result), AOP (left)))
4725 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4730 if (AOP_TYPE (right) == AOP_CRY)
4733 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4734 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4739 symbol *tlbl = newiTempLabel (NULL);
4740 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4741 emitcode ("setb", "c");
4742 emitcode ("jb", "%s,%05d$",
4743 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4745 emitcode ("jnz", "%05d$", tlbl->key + 100);
4746 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4748 jmpTrueOrFalse (ifx, tlbl);
4754 emitcode ("", "%05d$:", tlbl->key + 100);
4763 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4764 genIfxJump (ifx, "c");
4768 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4769 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4770 if ((AOP_TYPE (right) == AOP_LIT) &&
4771 (AOP_TYPE (result) == AOP_CRY) &&
4772 (AOP_TYPE (left) != AOP_CRY))
4778 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4780 continueIfTrue (ifx);
4785 // lit = 0, result = boolean(left)
4787 emitcode ("setb", "c");
4791 symbol *tlbl = newiTempLabel (NULL);
4792 emitcode ("jnz", "%05d$", tlbl->key + 100);
4794 emitcode ("", "%05d$:", tlbl->key + 100);
4798 genIfxJump (ifx, "a");
4806 /* if left is same as result */
4807 if (sameRegs (AOP (result), AOP (left)))
4809 for (; size--; offset++)
4811 if (AOP_TYPE (right) == AOP_LIT)
4813 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4815 else if (IS_AOP_PREG (left))
4817 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4818 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4819 aopPut (AOP (result), "a", offset);
4822 emitcode ("orl", "%s,%s",
4823 aopGet (AOP (left), offset, FALSE, TRUE),
4824 aopGet (AOP (right), offset, FALSE, FALSE));
4828 if (AOP_TYPE (left) == AOP_ACC)
4829 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4832 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4833 if (IS_AOP_PREG (left))
4835 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4836 aopPut (AOP (result), "a", offset);
4839 emitcode ("orl", "%s,a",
4840 aopGet (AOP (left), offset, FALSE, TRUE));
4847 // left & result in different registers
4848 if (AOP_TYPE (result) == AOP_CRY)
4851 // if(size), result in bit
4852 // if(!size && ifx), conditional oper: if(left | right)
4853 symbol *tlbl = newiTempLabel (NULL);
4854 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4856 emitcode ("setb", "c");
4859 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4860 emitcode ("orl", "a,%s",
4861 aopGet (AOP (left), offset, FALSE, FALSE));
4862 emitcode ("jnz", "%05d$", tlbl->key + 100);
4868 emitcode ("", "%05d$:", tlbl->key + 100);
4872 jmpTrueOrFalse (ifx, tlbl);
4875 for (; (size--); offset++)
4878 // result = left & right
4879 if (AOP_TYPE (right) == AOP_LIT)
4881 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4883 aopPut (AOP (result),
4884 aopGet (AOP (left), offset, FALSE, FALSE),
4889 // faster than result <- left, anl result,right
4890 // and better if result is SFR
4891 if (AOP_TYPE (left) == AOP_ACC)
4892 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4896 emitcode ("orl", "a,%s",
4897 aopGet (AOP (left), offset, FALSE, FALSE));
4899 aopPut (AOP (result), "a", offset);
4904 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4905 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4906 freeAsmop (result, NULL, ic, TRUE);
4909 /*-----------------------------------------------------------------*/
4910 /* genXor - code for xclusive or */
4911 /*-----------------------------------------------------------------*/
4913 genXor (iCode * ic, iCode * ifx)
4915 operand *left, *right, *result;
4916 int size, offset = 0;
4917 unsigned long lit = 0L;
4919 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4920 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4921 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4924 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4926 AOP_TYPE (left), AOP_TYPE (right));
4927 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4929 AOP_SIZE (left), AOP_SIZE (right));
4932 /* if left is a literal & right is not ||
4933 if left needs acc & right does not */
4934 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4935 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4937 operand *tmp = right;
4942 /* if result = right then exchange them */
4943 if (sameRegs (AOP (result), AOP (right)))
4945 operand *tmp = right;
4950 /* if right is bit then exchange them */
4951 if (AOP_TYPE (right) == AOP_CRY &&
4952 AOP_TYPE (left) != AOP_CRY)
4954 operand *tmp = right;
4958 if (AOP_TYPE (right) == AOP_LIT)
4959 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4961 size = AOP_SIZE (result);
4965 if (AOP_TYPE (left) == AOP_CRY)
4967 if (AOP_TYPE (right) == AOP_LIT)
4969 // c = bit & literal;
4972 // lit>>1 != 0 => result = 1
4973 if (AOP_TYPE (result) == AOP_CRY)
4976 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4978 continueIfTrue (ifx);
4981 emitcode ("setb", "c");
4988 // lit == 0, result = left
4989 if (size && sameRegs (AOP (result), AOP (left)))
4991 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4995 // lit == 1, result = not(left)
4996 if (size && sameRegs (AOP (result), AOP (left)))
4998 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5003 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5004 emitcode ("cpl", "c");
5013 symbol *tlbl = newiTempLabel (NULL);
5014 if (AOP_TYPE (right) == AOP_CRY)
5017 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5021 int sizer = AOP_SIZE (right);
5023 // if val>>1 != 0, result = 1
5024 emitcode ("setb", "c");
5027 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5029 // test the msb of the lsb
5030 emitcode ("anl", "a,#0xfe");
5031 emitcode ("jnz", "%05d$", tlbl->key + 100);
5035 emitcode ("rrc", "a");
5037 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5038 emitcode ("cpl", "c");
5039 emitcode ("", "%05d$:", (tlbl->key + 100));
5046 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5047 genIfxJump (ifx, "c");
5051 if (sameRegs (AOP (result), AOP (left)))
5053 /* if left is same as result */
5054 for (; size--; offset++)
5056 if (AOP_TYPE (right) == AOP_LIT)
5058 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5060 else if (IS_AOP_PREG (left))
5062 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5063 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5064 aopPut (AOP (result), "a", offset);
5067 emitcode ("xrl", "%s,%s",
5068 aopGet (AOP (left), offset, FALSE, TRUE),
5069 aopGet (AOP (right), offset, FALSE, FALSE));
5073 if (AOP_TYPE (left) == AOP_ACC)
5074 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5078 if (IS_AOP_PREG (left))
5080 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5081 aopPut (AOP (result), "a", offset);
5084 emitcode ("xrl", "%s,a",
5085 aopGet (AOP (left), offset, FALSE, TRUE));
5092 // left & result in different registers
5093 if (AOP_TYPE (result) == AOP_CRY)
5096 // if(size), result in bit
5097 // if(!size && ifx), conditional oper: if(left ^ right)
5098 symbol *tlbl = newiTempLabel (NULL);
5099 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5101 emitcode ("setb", "c");
5104 if ((AOP_TYPE (right) == AOP_LIT) &&
5105 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5107 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5111 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5112 emitcode ("xrl", "a,%s",
5113 aopGet (AOP (left), offset, FALSE, FALSE));
5115 emitcode ("jnz", "%05d$", tlbl->key + 100);
5121 emitcode ("", "%05d$:", tlbl->key + 100);
5125 jmpTrueOrFalse (ifx, tlbl);
5128 for (; (size--); offset++)
5131 // result = left & right
5132 if (AOP_TYPE (right) == AOP_LIT)
5134 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5136 aopPut (AOP (result),
5137 aopGet (AOP (left), offset, FALSE, FALSE),
5142 // faster than result <- left, anl result,right
5143 // and better if result is SFR
5144 if (AOP_TYPE (left) == AOP_ACC)
5145 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5148 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5149 emitcode ("xrl", "a,%s",
5150 aopGet (AOP (left), offset, FALSE, TRUE));
5152 aopPut (AOP (result), "a", offset);
5157 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5158 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5159 freeAsmop (result, NULL, ic, TRUE);
5162 /*-----------------------------------------------------------------*/
5163 /* genInline - write the inline code out */
5164 /*-----------------------------------------------------------------*/
5166 genInline (iCode * ic)
5168 char *buffer, *bp, *bp1;
5170 _G.inLine += (!options.asmpeep);
5172 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5173 strcpy (buffer, IC_INLINE (ic));
5175 /* emit each line as a code */
5200 /* emitcode("",buffer); */
5201 _G.inLine -= (!options.asmpeep);
5204 /*-----------------------------------------------------------------*/
5205 /* genRRC - rotate right with carry */
5206 /*-----------------------------------------------------------------*/
5210 operand *left, *result;
5211 int size, offset = 0;
5214 /* rotate right with carry */
5215 left = IC_LEFT (ic);
5216 result = IC_RESULT (ic);
5217 aopOp (left, ic, FALSE);
5218 aopOp (result, ic, FALSE);
5220 /* move it to the result */
5221 size = AOP_SIZE (result);
5226 l = aopGet (AOP (left), offset, FALSE, FALSE);
5228 emitcode ("rrc", "a");
5229 if (AOP_SIZE (result) > 1)
5230 aopPut (AOP (result), "a", offset--);
5232 /* now we need to put the carry into the
5233 highest order byte of the result */
5234 if (AOP_SIZE (result) > 1)
5236 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5239 emitcode ("mov", "acc.7,c");
5240 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5241 freeAsmop (left, NULL, ic, TRUE);
5242 freeAsmop (result, NULL, ic, TRUE);
5245 /*-----------------------------------------------------------------*/
5246 /* genRLC - generate code for rotate left with carry */
5247 /*-----------------------------------------------------------------*/
5251 operand *left, *result;
5252 int size, offset = 0;
5255 /* rotate right with carry */
5256 left = IC_LEFT (ic);
5257 result = IC_RESULT (ic);
5258 aopOp (left, ic, FALSE);
5259 aopOp (result, ic, FALSE);
5261 /* move it to the result */
5262 size = AOP_SIZE (result);
5266 l = aopGet (AOP (left), offset, FALSE, FALSE);
5268 emitcode ("add", "a,acc");
5269 if (AOP_SIZE (result) > 1)
5270 aopPut (AOP (result), "a", offset++);
5273 l = aopGet (AOP (left), offset, FALSE, FALSE);
5275 emitcode ("rlc", "a");
5276 if (AOP_SIZE (result) > 1)
5277 aopPut (AOP (result), "a", offset++);
5280 /* now we need to put the carry into the
5281 highest order byte of the result */
5282 if (AOP_SIZE (result) > 1)
5284 l = aopGet (AOP (result), 0, FALSE, FALSE);
5287 emitcode ("mov", "acc.0,c");
5288 aopPut (AOP (result), "a", 0);
5289 freeAsmop (left, NULL, ic, TRUE);
5290 freeAsmop (result, NULL, ic, TRUE);
5293 /*-----------------------------------------------------------------*/
5294 /* genGetHbit - generates code get highest order bit */
5295 /*-----------------------------------------------------------------*/
5297 genGetHbit (iCode * ic)
5299 operand *left, *result;
5300 left = IC_LEFT (ic);
5301 result = IC_RESULT (ic);
5302 aopOp (left, ic, FALSE);
5303 aopOp (result, ic, FALSE);
5305 /* get the highest order byte into a */
5306 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5307 if (AOP_TYPE (result) == AOP_CRY)
5309 emitcode ("rlc", "a");
5314 emitcode ("rl", "a");
5315 emitcode ("anl", "a,#0x01");
5320 freeAsmop (left, NULL, ic, TRUE);
5321 freeAsmop (result, NULL, ic, TRUE);
5324 /*-----------------------------------------------------------------*/
5325 /* AccRol - rotate left accumulator by known count */
5326 /*-----------------------------------------------------------------*/
5328 AccRol (int shCount)
5330 shCount &= 0x0007; // shCount : 0..7
5337 emitcode ("rl", "a");
5340 emitcode ("rl", "a");
5341 emitcode ("rl", "a");
5344 emitcode ("swap", "a");
5345 emitcode ("rr", "a");
5348 emitcode ("swap", "a");
5351 emitcode ("swap", "a");
5352 emitcode ("rl", "a");
5355 emitcode ("rr", "a");
5356 emitcode ("rr", "a");
5359 emitcode ("rr", "a");
5364 /*-----------------------------------------------------------------*/
5365 /* AccLsh - left shift accumulator by known count */
5366 /*-----------------------------------------------------------------*/
5368 AccLsh (int shCount)
5373 emitcode ("add", "a,acc");
5374 else if (shCount == 2)
5376 emitcode ("add", "a,acc");
5377 emitcode ("add", "a,acc");
5381 /* rotate left accumulator */
5383 /* and kill the lower order bits */
5384 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5389 /*-----------------------------------------------------------------*/
5390 /* AccRsh - right shift accumulator by known count */
5391 /*-----------------------------------------------------------------*/
5393 AccRsh (int shCount)
5400 emitcode ("rrc", "a");
5404 /* rotate right accumulator */
5405 AccRol (8 - shCount);
5406 /* and kill the higher order bits */
5407 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5412 /*-----------------------------------------------------------------*/
5413 /* AccSRsh - signed right shift accumulator by known count */
5414 /*-----------------------------------------------------------------*/
5416 AccSRsh (int shCount)
5423 emitcode ("mov", "c,acc.7");
5424 emitcode ("rrc", "a");
5426 else if (shCount == 2)
5428 emitcode ("mov", "c,acc.7");
5429 emitcode ("rrc", "a");
5430 emitcode ("mov", "c,acc.7");
5431 emitcode ("rrc", "a");
5435 tlbl = newiTempLabel (NULL);
5436 /* rotate right accumulator */
5437 AccRol (8 - shCount);
5438 /* and kill the higher order bits */
5439 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5440 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5441 emitcode ("orl", "a,#0x%02x",
5442 (unsigned char) ~SRMask[shCount]);
5443 emitcode ("", "%05d$:", tlbl->key + 100);
5448 /*-----------------------------------------------------------------*/
5449 /* shiftR1Left2Result - shift right one byte from left to result */
5450 /*-----------------------------------------------------------------*/
5452 shiftR1Left2Result (operand * left, int offl,
5453 operand * result, int offr,
5454 int shCount, int sign)
5456 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5457 /* shift right accumulator */
5462 aopPut (AOP (result), "a", offr);
5465 /*-----------------------------------------------------------------*/
5466 /* shiftL1Left2Result - shift left one byte from left to result */
5467 /*-----------------------------------------------------------------*/
5469 shiftL1Left2Result (operand * left, int offl,
5470 operand * result, int offr, int shCount)
5473 l = aopGet (AOP (left), offl, FALSE, FALSE);
5475 /* shift left accumulator */
5477 aopPut (AOP (result), "a", offr);
5480 /*-----------------------------------------------------------------*/
5481 /* movLeft2Result - move byte from left to result */
5482 /*-----------------------------------------------------------------*/
5484 movLeft2Result (operand * left, int offl,
5485 operand * result, int offr, int sign)
5488 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5490 l = aopGet (AOP (left), offl, FALSE, FALSE);
5492 if (*l == '@' && (IS_AOP_PREG (result)))
5494 emitcode ("mov", "a,%s", l);
5495 aopPut (AOP (result), "a", offr);
5500 aopPut (AOP (result), l, offr);
5503 /* MSB sign in acc.7 ! */
5504 if (getDataSize (left) == offl + 1)
5506 emitcode ("mov", "a,%s", l);
5507 aopPut (AOP (result), "a", offr);
5514 /*-----------------------------------------------------------------*/
5515 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5516 /*-----------------------------------------------------------------*/
5520 emitcode ("rrc", "a");
5521 emitcode ("xch", "a,%s", x);
5522 emitcode ("rrc", "a");
5523 emitcode ("xch", "a,%s", x);
5526 /*-----------------------------------------------------------------*/
5527 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5528 /*-----------------------------------------------------------------*/
5532 emitcode ("xch", "a,%s", x);
5533 emitcode ("rlc", "a");
5534 emitcode ("xch", "a,%s", x);
5535 emitcode ("rlc", "a");
5538 /*-----------------------------------------------------------------*/
5539 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5540 /*-----------------------------------------------------------------*/
5544 emitcode ("xch", "a,%s", x);
5545 emitcode ("add", "a,acc");
5546 emitcode ("xch", "a,%s", x);
5547 emitcode ("rlc", "a");
5550 /*-----------------------------------------------------------------*/
5551 /* AccAXLsh - left shift a:x by known count (0..7) */
5552 /*-----------------------------------------------------------------*/
5554 AccAXLsh (char *x, int shCount)
5569 case 5: // AAAAABBB:CCCCCDDD
5571 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5573 emitcode ("anl", "a,#0x%02x",
5574 SLMask[shCount]); // BBB00000:CCCCCDDD
5576 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5578 AccRol (shCount); // DDDCCCCC:BBB00000
5580 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5582 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5584 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5586 emitcode ("anl", "a,#0x%02x",
5587 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5589 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5591 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5594 case 6: // AAAAAABB:CCCCCCDD
5595 emitcode ("anl", "a,#0x%02x",
5596 SRMask[shCount]); // 000000BB:CCCCCCDD
5597 emitcode ("mov", "c,acc.0"); // c = B
5598 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5600 AccAXRrl1 (x); // BCCCCCCD:D000000B
5601 AccAXRrl1 (x); // BBCCCCCC:DD000000
5603 emitcode("rrc","a");
5604 emitcode("xch","a,%s", x);
5605 emitcode("rrc","a");
5606 emitcode("mov","c,acc.0"); //<< get correct bit
5607 emitcode("xch","a,%s", x);
5609 emitcode("rrc","a");
5610 emitcode("xch","a,%s", x);
5611 emitcode("rrc","a");
5612 emitcode("xch","a,%s", x);
5615 case 7: // a:x <<= 7
5617 emitcode ("anl", "a,#0x%02x",
5618 SRMask[shCount]); // 0000000B:CCCCCCCD
5620 emitcode ("mov", "c,acc.0"); // c = B
5622 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5624 AccAXRrl1 (x); // BCCCCCCC:D0000000
5632 /*-----------------------------------------------------------------*/
5633 /* AccAXRsh - right shift a:x known count (0..7) */
5634 /*-----------------------------------------------------------------*/
5636 AccAXRsh (char *x, int shCount)
5644 AccAXRrl1 (x); // 0->a:x
5649 AccAXRrl1 (x); // 0->a:x
5652 AccAXRrl1 (x); // 0->a:x
5657 case 5: // AAAAABBB:CCCCCDDD = a:x
5659 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5661 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5663 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5665 emitcode ("anl", "a,#0x%02x",
5666 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5668 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5670 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5672 emitcode ("anl", "a,#0x%02x",
5673 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5675 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5677 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5679 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5682 case 6: // AABBBBBB:CCDDDDDD
5684 emitcode ("mov", "c,acc.7");
5685 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5687 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5689 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5691 emitcode ("anl", "a,#0x%02x",
5692 SRMask[shCount]); // 000000AA:BBBBBBCC
5695 case 7: // ABBBBBBB:CDDDDDDD
5697 emitcode ("mov", "c,acc.7"); // c = A
5699 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5701 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5703 emitcode ("anl", "a,#0x%02x",
5704 SRMask[shCount]); // 0000000A:BBBBBBBC
5712 /*-----------------------------------------------------------------*/
5713 /* AccAXRshS - right shift signed a:x known count (0..7) */
5714 /*-----------------------------------------------------------------*/
5716 AccAXRshS (char *x, int shCount)
5724 emitcode ("mov", "c,acc.7");
5725 AccAXRrl1 (x); // s->a:x
5729 emitcode ("mov", "c,acc.7");
5730 AccAXRrl1 (x); // s->a:x
5732 emitcode ("mov", "c,acc.7");
5733 AccAXRrl1 (x); // s->a:x
5738 case 5: // AAAAABBB:CCCCCDDD = a:x
5740 tlbl = newiTempLabel (NULL);
5741 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5743 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5745 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5747 emitcode ("anl", "a,#0x%02x",
5748 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5750 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5752 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5754 emitcode ("anl", "a,#0x%02x",
5755 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5757 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5759 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5761 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5763 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5764 emitcode ("orl", "a,#0x%02x",
5765 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5767 emitcode ("", "%05d$:", tlbl->key + 100);
5768 break; // SSSSAAAA:BBBCCCCC
5770 case 6: // AABBBBBB:CCDDDDDD
5772 tlbl = newiTempLabel (NULL);
5773 emitcode ("mov", "c,acc.7");
5774 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5776 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5778 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5780 emitcode ("anl", "a,#0x%02x",
5781 SRMask[shCount]); // 000000AA:BBBBBBCC
5783 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5784 emitcode ("orl", "a,#0x%02x",
5785 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5787 emitcode ("", "%05d$:", tlbl->key + 100);
5789 case 7: // ABBBBBBB:CDDDDDDD
5791 tlbl = newiTempLabel (NULL);
5792 emitcode ("mov", "c,acc.7"); // c = A
5794 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5796 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5798 emitcode ("anl", "a,#0x%02x",
5799 SRMask[shCount]); // 0000000A:BBBBBBBC
5801 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5802 emitcode ("orl", "a,#0x%02x",
5803 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5805 emitcode ("", "%05d$:", tlbl->key + 100);
5812 /*-----------------------------------------------------------------*/
5813 /* shiftL2Left2Result - shift left two bytes from left to result */
5814 /*-----------------------------------------------------------------*/
5816 shiftL2Left2Result (operand * left, int offl,
5817 operand * result, int offr, int shCount)
5819 if (sameRegs (AOP (result), AOP (left)) &&
5820 ((offl + MSB16) == offr))
5822 /* don't crash result[offr] */
5823 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5824 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5828 movLeft2Result (left, offl, result, offr, 0);
5829 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5831 /* ax << shCount (x = lsb(result)) */
5832 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5833 aopPut (AOP (result), "a", offr + MSB16);
5837 /*-----------------------------------------------------------------*/
5838 /* shiftR2Left2Result - shift right two bytes from left to result */
5839 /*-----------------------------------------------------------------*/
5841 shiftR2Left2Result (operand * left, int offl,
5842 operand * result, int offr,
5843 int shCount, int sign)
5845 if (sameRegs (AOP (result), AOP (left)) &&
5846 ((offl + MSB16) == offr))
5848 /* don't crash result[offr] */
5849 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5850 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5854 movLeft2Result (left, offl, result, offr, 0);
5855 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5857 /* a:x >> shCount (x = lsb(result)) */
5859 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5861 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5862 if (getDataSize (result) > 1)
5863 aopPut (AOP (result), "a", offr + MSB16);
5866 /*-----------------------------------------------------------------*/
5867 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5868 /*-----------------------------------------------------------------*/
5870 shiftLLeftOrResult (operand * left, int offl,
5871 operand * result, int offr, int shCount)
5873 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5874 /* shift left accumulator */
5876 /* or with result */
5877 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5878 /* back to result */
5879 aopPut (AOP (result), "a", offr);
5882 /*-----------------------------------------------------------------*/
5883 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5884 /*-----------------------------------------------------------------*/
5886 shiftRLeftOrResult (operand * left, int offl,
5887 operand * result, int offr, int shCount)
5889 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5890 /* shift right accumulator */
5892 /* or with result */
5893 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5894 /* back to result */
5895 aopPut (AOP (result), "a", offr);
5898 /*-----------------------------------------------------------------*/
5899 /* genlshOne - left shift a one byte quantity by known count */
5900 /*-----------------------------------------------------------------*/
5902 genlshOne (operand * result, operand * left, int shCount)
5904 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5907 /*-----------------------------------------------------------------*/
5908 /* genlshTwo - left shift two bytes by known amount != 0 */
5909 /*-----------------------------------------------------------------*/
5911 genlshTwo (operand * result, operand * left, int shCount)
5915 size = getDataSize (result);
5917 /* if shCount >= 8 */
5925 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5927 movLeft2Result (left, LSB, result, MSB16, 0);
5929 aopPut (AOP (result), zero, LSB);
5932 /* 1 <= shCount <= 7 */
5936 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5938 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5942 /*-----------------------------------------------------------------*/
5943 /* shiftLLong - shift left one long from left to result */
5944 /* offl = LSB or MSB16 */
5945 /*-----------------------------------------------------------------*/
5947 shiftLLong (operand * left, operand * result, int offr)
5950 int size = AOP_SIZE (result);
5952 if (size >= LSB + offr)
5954 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5956 emitcode ("add", "a,acc");
5957 if (sameRegs (AOP (left), AOP (result)) &&
5958 size >= MSB16 + offr && offr != LSB)
5959 emitcode ("xch", "a,%s",
5960 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5962 aopPut (AOP (result), "a", LSB + offr);
5965 if (size >= MSB16 + offr)
5967 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5969 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5972 emitcode ("rlc", "a");
5973 if (sameRegs (AOP (left), AOP (result)) &&
5974 size >= MSB24 + offr && offr != LSB)
5975 emitcode ("xch", "a,%s",
5976 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5978 aopPut (AOP (result), "a", MSB16 + offr);
5981 if (size >= MSB24 + offr)
5983 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5985 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5988 emitcode ("rlc", "a");
5989 if (sameRegs (AOP (left), AOP (result)) &&
5990 size >= MSB32 + offr && offr != LSB)
5991 emitcode ("xch", "a,%s",
5992 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5994 aopPut (AOP (result), "a", MSB24 + offr);
5997 if (size > MSB32 + offr)
5999 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6001 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6004 emitcode ("rlc", "a");
6005 aopPut (AOP (result), "a", MSB32 + offr);
6008 aopPut (AOP (result), zero, LSB);
6011 /*-----------------------------------------------------------------*/
6012 /* genlshFour - shift four byte by a known amount != 0 */
6013 /*-----------------------------------------------------------------*/
6015 genlshFour (operand * result, operand * left, int shCount)
6019 size = AOP_SIZE (result);
6021 /* if shifting more that 3 bytes */
6026 /* lowest order of left goes to the highest
6027 order of the destination */
6028 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6030 movLeft2Result (left, LSB, result, MSB32, 0);
6031 aopPut (AOP (result), zero, LSB);
6032 aopPut (AOP (result), zero, MSB16);
6033 aopPut (AOP (result), zero, MSB24);
6037 /* more than two bytes */
6038 else if (shCount >= 16)
6040 /* lower order two bytes goes to higher order two bytes */
6042 /* if some more remaining */
6044 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6047 movLeft2Result (left, MSB16, result, MSB32, 0);
6048 movLeft2Result (left, LSB, result, MSB24, 0);
6050 aopPut (AOP (result), zero, MSB16);
6051 aopPut (AOP (result), zero, LSB);
6055 /* if more than 1 byte */
6056 else if (shCount >= 8)
6058 /* lower order three bytes goes to higher order three bytes */
6063 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6065 movLeft2Result (left, LSB, result, MSB16, 0);
6071 movLeft2Result (left, MSB24, result, MSB32, 0);
6072 movLeft2Result (left, MSB16, result, MSB24, 0);
6073 movLeft2Result (left, LSB, result, MSB16, 0);
6074 aopPut (AOP (result), zero, LSB);
6076 else if (shCount == 1)
6077 shiftLLong (left, result, MSB16);
6080 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6081 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6082 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6083 aopPut (AOP (result), zero, LSB);
6088 /* 1 <= shCount <= 7 */
6089 else if (shCount <= 2)
6091 shiftLLong (left, result, LSB);
6093 shiftLLong (result, result, LSB);
6095 /* 3 <= shCount <= 7, optimize */
6098 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6099 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6100 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6104 /*-----------------------------------------------------------------*/
6105 /* genLeftShiftLiteral - left shifting by known count */
6106 /*-----------------------------------------------------------------*/
6108 genLeftShiftLiteral (operand * left,
6113 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6116 freeAsmop (right, NULL, ic, TRUE);
6118 aopOp (left, ic, FALSE);
6119 aopOp (result, ic, FALSE);
6121 size = getSize (operandType (result));
6124 emitcode ("; shift left ", "result %d, left %d", size,
6128 /* I suppose that the left size >= result size */
6133 movLeft2Result (left, size, result, size, 0);
6137 else if (shCount >= (size * 8))
6139 aopPut (AOP (result), zero, size);
6145 genlshOne (result, left, shCount);
6150 genlshTwo (result, left, shCount);
6154 genlshFour (result, left, shCount);
6158 freeAsmop (left, NULL, ic, TRUE);
6159 freeAsmop (result, NULL, ic, TRUE);
6162 /*-----------------------------------------------------------------*/
6163 /* genLeftShift - generates code for left shifting */
6164 /*-----------------------------------------------------------------*/
6166 genLeftShift (iCode * ic)
6168 operand *left, *right, *result;
6171 symbol *tlbl, *tlbl1;
6173 right = IC_RIGHT (ic);
6174 left = IC_LEFT (ic);
6175 result = IC_RESULT (ic);
6177 aopOp (right, ic, FALSE);
6179 /* if the shift count is known then do it
6180 as efficiently as possible */
6181 if (AOP_TYPE (right) == AOP_LIT)
6183 genLeftShiftLiteral (left, right, result, ic);
6187 /* shift count is unknown then we have to form
6188 a loop get the loop count in B : Note: we take
6189 only the lower order byte since shifting
6190 more that 32 bits make no sense anyway, ( the
6191 largest size of an object can be only 32 bits ) */
6193 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6194 emitcode ("inc", "b");
6195 freeAsmop (right, NULL, ic, TRUE);
6196 aopOp (left, ic, FALSE);
6197 aopOp (result, ic, FALSE);
6199 /* now move the left to the result if they are not the
6201 if (!sameRegs (AOP (left), AOP (result)) &&
6202 AOP_SIZE (result) > 1)
6205 size = AOP_SIZE (result);
6209 l = aopGet (AOP (left), offset, FALSE, TRUE);
6210 if (*l == '@' && (IS_AOP_PREG (result)))
6213 emitcode ("mov", "a,%s", l);
6214 aopPut (AOP (result), "a", offset);
6217 aopPut (AOP (result), l, offset);
6222 tlbl = newiTempLabel (NULL);
6223 size = AOP_SIZE (result);
6225 tlbl1 = newiTempLabel (NULL);
6227 /* if it is only one byte then */
6230 symbol *tlbl1 = newiTempLabel (NULL);
6232 l = aopGet (AOP (left), 0, FALSE, FALSE);
6234 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6235 emitcode ("", "%05d$:", tlbl->key + 100);
6236 emitcode ("add", "a,acc");
6237 emitcode ("", "%05d$:", tlbl1->key + 100);
6238 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6239 aopPut (AOP (result), "a", 0);
6243 reAdjustPreg (AOP (result));
6245 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6246 emitcode ("", "%05d$:", tlbl->key + 100);
6247 l = aopGet (AOP (result), offset, FALSE, FALSE);
6249 emitcode ("add", "a,acc");
6250 aopPut (AOP (result), "a", offset++);
6253 l = aopGet (AOP (result), offset, FALSE, FALSE);
6255 emitcode ("rlc", "a");
6256 aopPut (AOP (result), "a", offset++);
6258 reAdjustPreg (AOP (result));
6260 emitcode ("", "%05d$:", tlbl1->key + 100);
6261 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6263 freeAsmop (left, NULL, ic, TRUE);
6264 freeAsmop (result, NULL, ic, TRUE);
6267 /*-----------------------------------------------------------------*/
6268 /* genrshOne - right shift a one byte quantity by known count */
6269 /*-----------------------------------------------------------------*/
6271 genrshOne (operand * result, operand * left,
6272 int shCount, int sign)
6274 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6277 /*-----------------------------------------------------------------*/
6278 /* genrshTwo - right shift two bytes by known amount != 0 */
6279 /*-----------------------------------------------------------------*/
6281 genrshTwo (operand * result, operand * left,
6282 int shCount, int sign)
6284 /* if shCount >= 8 */
6289 shiftR1Left2Result (left, MSB16, result, LSB,
6292 movLeft2Result (left, MSB16, result, LSB, sign);
6293 addSign (result, MSB16, sign);
6296 /* 1 <= shCount <= 7 */
6298 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6301 /*-----------------------------------------------------------------*/
6302 /* shiftRLong - shift right one long from left to result */
6303 /* offl = LSB or MSB16 */
6304 /*-----------------------------------------------------------------*/
6306 shiftRLong (operand * left, int offl,
6307 operand * result, int sign)
6310 emitcode ("clr", "c");
6311 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6313 emitcode ("mov", "c,acc.7");
6314 emitcode ("rrc", "a");
6315 aopPut (AOP (result), "a", MSB32 - offl);
6317 /* add sign of "a" */
6318 addSign (result, MSB32, sign);
6320 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6321 emitcode ("rrc", "a");
6322 aopPut (AOP (result), "a", MSB24 - offl);
6324 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6325 emitcode ("rrc", "a");
6326 aopPut (AOP (result), "a", MSB16 - offl);
6330 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6331 emitcode ("rrc", "a");
6332 aopPut (AOP (result), "a", LSB);
6336 /*-----------------------------------------------------------------*/
6337 /* genrshFour - shift four byte by a known amount != 0 */
6338 /*-----------------------------------------------------------------*/
6340 genrshFour (operand * result, operand * left,
6341 int shCount, int sign)
6343 /* if shifting more that 3 bytes */
6348 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6350 movLeft2Result (left, MSB32, result, LSB, sign);
6351 addSign (result, MSB16, sign);
6353 else if (shCount >= 16)
6357 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6360 movLeft2Result (left, MSB24, result, LSB, 0);
6361 movLeft2Result (left, MSB32, result, MSB16, sign);
6363 addSign (result, MSB24, sign);
6365 else if (shCount >= 8)
6369 shiftRLong (left, MSB16, result, sign);
6370 else if (shCount == 0)
6372 movLeft2Result (left, MSB16, result, LSB, 0);
6373 movLeft2Result (left, MSB24, result, MSB16, 0);
6374 movLeft2Result (left, MSB32, result, MSB24, sign);
6375 addSign (result, MSB32, sign);
6379 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6380 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6381 /* the last shift is signed */
6382 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6383 addSign (result, MSB32, sign);
6387 { /* 1 <= shCount <= 7 */
6390 shiftRLong (left, LSB, result, sign);
6392 shiftRLong (result, LSB, result, sign);
6396 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6397 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6398 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6403 /*-----------------------------------------------------------------*/
6404 /* genRightShiftLiteral - right shifting by known count */
6405 /*-----------------------------------------------------------------*/
6407 genRightShiftLiteral (operand * left,
6413 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6416 freeAsmop (right, NULL, ic, TRUE);
6418 aopOp (left, ic, FALSE);
6419 aopOp (result, ic, FALSE);
6422 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6426 size = getDataSize (left);
6427 /* test the LEFT size !!! */
6429 /* I suppose that the left size >= result size */
6432 size = getDataSize (result);
6434 movLeft2Result (left, size, result, size, 0);
6437 else if (shCount >= (size * 8))
6440 /* get sign in acc.7 */
6441 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6442 addSign (result, LSB, sign);
6449 genrshOne (result, left, shCount, sign);
6453 genrshTwo (result, left, shCount, sign);
6457 genrshFour (result, left, shCount, sign);
6463 freeAsmop (left, NULL, ic, TRUE);
6464 freeAsmop (result, NULL, ic, TRUE);
6468 /*-----------------------------------------------------------------*/
6469 /* genSignedRightShift - right shift of signed number */
6470 /*-----------------------------------------------------------------*/
6472 genSignedRightShift (iCode * ic)
6474 operand *right, *left, *result;
6477 symbol *tlbl, *tlbl1;
6479 /* we do it the hard way put the shift count in b
6480 and loop thru preserving the sign */
6482 right = IC_RIGHT (ic);
6483 left = IC_LEFT (ic);
6484 result = IC_RESULT (ic);
6486 aopOp (right, ic, FALSE);
6489 if (AOP_TYPE (right) == AOP_LIT)
6491 genRightShiftLiteral (left, right, result, ic, 1);
6494 /* shift count is unknown then we have to form
6495 a loop get the loop count in B : Note: we take
6496 only the lower order byte since shifting
6497 more that 32 bits make no sense anyway, ( the
6498 largest size of an object can be only 32 bits ) */
6500 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6501 emitcode ("inc", "b");
6502 freeAsmop (right, NULL, ic, TRUE);
6503 aopOp (left, ic, FALSE);
6504 aopOp (result, ic, FALSE);
6506 /* now move the left to the result if they are not the
6508 if (!sameRegs (AOP (left), AOP (result)) &&
6509 AOP_SIZE (result) > 1)
6512 size = AOP_SIZE (result);
6516 l = aopGet (AOP (left), offset, FALSE, TRUE);
6517 if (*l == '@' && IS_AOP_PREG (result))
6520 emitcode ("mov", "a,%s", l);
6521 aopPut (AOP (result), "a", offset);
6524 aopPut (AOP (result), l, offset);
6529 /* mov the highest order bit to OVR */
6530 tlbl = newiTempLabel (NULL);
6531 tlbl1 = newiTempLabel (NULL);
6533 size = AOP_SIZE (result);
6535 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6536 emitcode ("rlc", "a");
6537 emitcode ("mov", "ov,c");
6538 /* if it is only one byte then */
6541 l = aopGet (AOP (left), 0, FALSE, FALSE);
6543 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6544 emitcode ("", "%05d$:", tlbl->key + 100);
6545 emitcode ("mov", "c,ov");
6546 emitcode ("rrc", "a");
6547 emitcode ("", "%05d$:", tlbl1->key + 100);
6548 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6549 aopPut (AOP (result), "a", 0);
6553 reAdjustPreg (AOP (result));
6554 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6555 emitcode ("", "%05d$:", tlbl->key + 100);
6556 emitcode ("mov", "c,ov");
6559 l = aopGet (AOP (result), offset, FALSE, FALSE);
6561 emitcode ("rrc", "a");
6562 aopPut (AOP (result), "a", offset--);
6564 reAdjustPreg (AOP (result));
6565 emitcode ("", "%05d$:", tlbl1->key + 100);
6566 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6569 freeAsmop (left, NULL, ic, TRUE);
6570 freeAsmop (result, NULL, ic, TRUE);
6573 /*-----------------------------------------------------------------*/
6574 /* genRightShift - generate code for right shifting */
6575 /*-----------------------------------------------------------------*/
6577 genRightShift (iCode * ic)
6579 operand *right, *left, *result;
6583 symbol *tlbl, *tlbl1;
6585 /* if signed then we do it the hard way preserve the
6586 sign bit moving it inwards */
6587 retype = getSpec (operandType (IC_RESULT (ic)));
6589 if (!SPEC_USIGN (retype))
6591 genSignedRightShift (ic);
6595 /* signed & unsigned types are treated the same : i.e. the
6596 signed is NOT propagated inwards : quoting from the
6597 ANSI - standard : "for E1 >> E2, is equivalent to division
6598 by 2**E2 if unsigned or if it has a non-negative value,
6599 otherwise the result is implementation defined ", MY definition
6600 is that the sign does not get propagated */
6602 right = IC_RIGHT (ic);
6603 left = IC_LEFT (ic);
6604 result = IC_RESULT (ic);
6606 aopOp (right, ic, FALSE);
6608 /* if the shift count is known then do it
6609 as efficiently as possible */
6610 if (AOP_TYPE (right) == AOP_LIT)
6612 genRightShiftLiteral (left, right, result, ic, 0);
6616 /* shift count is unknown then we have to form
6617 a loop get the loop count in B : Note: we take
6618 only the lower order byte since shifting
6619 more that 32 bits make no sense anyway, ( the
6620 largest size of an object can be only 32 bits ) */
6622 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6623 emitcode ("inc", "b");
6624 freeAsmop (right, NULL, ic, TRUE);
6625 aopOp (left, ic, FALSE);
6626 aopOp (result, ic, FALSE);
6628 /* now move the left to the result if they are not the
6630 if (!sameRegs (AOP (left), AOP (result)) &&
6631 AOP_SIZE (result) > 1)
6634 size = AOP_SIZE (result);
6638 l = aopGet (AOP (left), offset, FALSE, TRUE);
6639 if (*l == '@' && IS_AOP_PREG (result))
6642 emitcode ("mov", "a,%s", l);
6643 aopPut (AOP (result), "a", offset);
6646 aopPut (AOP (result), l, offset);
6651 tlbl = newiTempLabel (NULL);
6652 tlbl1 = newiTempLabel (NULL);
6653 size = AOP_SIZE (result);
6656 /* if it is only one byte then */
6659 l = aopGet (AOP (left), 0, FALSE, FALSE);
6661 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6662 emitcode ("", "%05d$:", tlbl->key + 100);
6664 emitcode ("rrc", "a");
6665 emitcode ("", "%05d$:", tlbl1->key + 100);
6666 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6667 aopPut (AOP (result), "a", 0);
6671 reAdjustPreg (AOP (result));
6672 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6673 emitcode ("", "%05d$:", tlbl->key + 100);
6677 l = aopGet (AOP (result), offset, FALSE, FALSE);
6679 emitcode ("rrc", "a");
6680 aopPut (AOP (result), "a", offset--);
6682 reAdjustPreg (AOP (result));
6684 emitcode ("", "%05d$:", tlbl1->key + 100);
6685 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6688 freeAsmop (left, NULL, ic, TRUE);
6689 freeAsmop (result, NULL, ic, TRUE);
6692 /*-----------------------------------------------------------------*/
6693 /* genUnpackBits - generates code for unpacking bits */
6694 /*-----------------------------------------------------------------*/
6696 genUnpackBits (operand * result, char *rname, int ptype)
6704 etype = getSpec (operandType (result));
6705 rsize = getSize (operandType (result));
6706 /* read the first byte */
6712 emitcode ("mov", "a,@%s", rname);
6716 emitcode ("movx", "a,@%s", rname);
6720 emitcode ("movx", "a,@dptr");
6724 emitcode ("clr", "a");
6725 emitcode ("movc", "a,%s", "@a+dptr");
6729 emitcode ("lcall", "__gptrget");
6733 rlen = SPEC_BLEN (etype);
6735 /* if we have bitdisplacement then it fits */
6736 /* into this byte completely or if length is */
6737 /* less than a byte */
6738 if ((shCnt = SPEC_BSTR (etype)) ||
6739 (SPEC_BLEN (etype) <= 8))
6742 /* shift right acc */
6745 emitcode ("anl", "a,#0x%02x",
6746 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6747 aopPut (AOP (result), "a", offset++);
6751 /* bit field did not fit in a byte */
6752 aopPut (AOP (result), "a", offset++);
6761 emitcode ("inc", "%s", rname);
6762 emitcode ("mov", "a,@%s", rname);
6766 emitcode ("inc", "%s", rname);
6767 emitcode ("movx", "a,@%s", rname);
6771 emitcode ("inc", "dptr");
6772 emitcode ("movx", "a,@dptr");
6776 emitcode ("clr", "a");
6777 emitcode ("inc", "dptr");
6778 emitcode ("movc", "a", "@a+dptr");
6782 emitcode ("inc", "dptr");
6783 emitcode ("lcall", "__gptrget");
6788 /* if we are done */
6792 aopPut (AOP (result), "a", offset++);
6798 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6800 aopPut (AOP (result), "a", offset++);
6808 aopPut (AOP (result), zero, offset++);
6814 /*-----------------------------------------------------------------*/
6815 /* genDataPointerGet - generates code when ptr offset is known */
6816 /*-----------------------------------------------------------------*/
6818 genDataPointerGet (operand * left,
6824 int size, offset = 0;
6825 aopOp (result, ic, TRUE);
6827 /* get the string representation of the name */
6828 l = aopGet (AOP (left), 0, FALSE, TRUE);
6829 size = AOP_SIZE (result);
6833 sprintf (buffer, "(%s + %d)", l + 1, offset);
6835 sprintf (buffer, "%s", l + 1);
6836 aopPut (AOP (result), buffer, offset++);
6839 freeAsmop (left, NULL, ic, TRUE);
6840 freeAsmop (result, NULL, ic, TRUE);
6843 /*-----------------------------------------------------------------*/
6844 /* genNearPointerGet - emitcode for near pointer fetch */
6845 /*-----------------------------------------------------------------*/
6847 genNearPointerGet (operand * left,
6855 sym_link *rtype, *retype;
6856 sym_link *ltype = operandType (left);
6859 rtype = operandType (result);
6860 retype = getSpec (rtype);
6862 aopOp (left, ic, FALSE);
6864 /* if left is rematerialisable and
6865 result is not bit variable type and
6866 the left is pointer to data space i.e
6867 lower 128 bytes of space */
6868 if (AOP_TYPE (left) == AOP_IMMD &&
6869 !IS_BITVAR (retype) &&
6870 DCL_TYPE (ltype) == POINTER)
6872 genDataPointerGet (left, result, ic);
6876 /* if the value is already in a pointer register
6877 then don't need anything more */
6878 if (!AOP_INPREG (AOP (left)))
6880 /* otherwise get a free pointer register */
6882 preg = getFreePtr (ic, &aop, FALSE);
6883 emitcode ("mov", "%s,%s",
6885 aopGet (AOP (left), 0, FALSE, TRUE));
6889 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6891 aopOp (result, ic, FALSE);
6893 /* if bitfield then unpack the bits */
6894 if (IS_BITVAR (retype))
6895 genUnpackBits (result, rname, POINTER);
6898 /* we have can just get the values */
6899 int size = AOP_SIZE (result);
6904 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6907 emitcode ("mov", "a,@%s", rname);
6908 aopPut (AOP (result), "a", offset);
6912 sprintf (buffer, "@%s", rname);
6913 aopPut (AOP (result), buffer, offset);
6917 emitcode ("inc", "%s", rname);
6921 /* now some housekeeping stuff */
6922 if (aop) /* we had to allocate for this iCode */
6924 if (pi) { /* post increment present */
6925 aopPut(AOP ( left ),rname,0);
6927 freeAsmop (NULL, aop, ic, TRUE);
6931 /* we did not allocate which means left
6932 already in a pointer register, then
6933 if size > 0 && this could be used again
6934 we have to point it back to where it
6936 if ((AOP_SIZE (result) > 1 &&
6937 !OP_SYMBOL (left)->remat &&
6938 (OP_SYMBOL (left)->liveTo > ic->seq ||
6942 int size = AOP_SIZE (result) - 1;
6944 emitcode ("dec", "%s", rname);
6949 freeAsmop (left, NULL, ic, TRUE);
6950 freeAsmop (result, NULL, ic, TRUE);
6951 if (pi) pi->generated = 1;
6954 /*-----------------------------------------------------------------*/
6955 /* genPagedPointerGet - emitcode for paged pointer fetch */
6956 /*-----------------------------------------------------------------*/
6958 genPagedPointerGet (operand * left,
6966 sym_link *rtype, *retype;
6968 rtype = operandType (result);
6969 retype = getSpec (rtype);
6971 aopOp (left, ic, FALSE);
6973 /* if the value is already in a pointer register
6974 then don't need anything more */
6975 if (!AOP_INPREG (AOP (left)))
6977 /* otherwise get a free pointer register */
6979 preg = getFreePtr (ic, &aop, FALSE);
6980 emitcode ("mov", "%s,%s",
6982 aopGet (AOP (left), 0, FALSE, TRUE));
6986 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6988 aopOp (result, ic, FALSE);
6990 /* if bitfield then unpack the bits */
6991 if (IS_BITVAR (retype))
6992 genUnpackBits (result, rname, PPOINTER);
6995 /* we have can just get the values */
6996 int size = AOP_SIZE (result);
7002 emitcode ("movx", "a,@%s", rname);
7003 aopPut (AOP (result), "a", offset);
7008 emitcode ("inc", "%s", rname);
7012 /* now some housekeeping stuff */
7013 if (aop) /* we had to allocate for this iCode */
7015 if (pi) aopPut ( AOP (left), rname, 0);
7016 freeAsmop (NULL, aop, ic, TRUE);
7020 /* we did not allocate which means left
7021 already in a pointer register, then
7022 if size > 0 && this could be used again
7023 we have to point it back to where it
7025 if ((AOP_SIZE (result) > 1 &&
7026 !OP_SYMBOL (left)->remat &&
7027 (OP_SYMBOL (left)->liveTo > ic->seq ||
7031 int size = AOP_SIZE (result) - 1;
7033 emitcode ("dec", "%s", rname);
7038 freeAsmop (left, NULL, ic, TRUE);
7039 freeAsmop (result, NULL, ic, TRUE);
7040 if (pi) pi->generated = 1;
7044 /*-----------------------------------------------------------------*/
7045 /* genFarPointerGet - gget value from far space */
7046 /*-----------------------------------------------------------------*/
7048 genFarPointerGet (operand * left,
7049 operand * result, iCode * ic, iCode * pi)
7052 sym_link *retype = getSpec (operandType (result));
7054 aopOp (left, ic, FALSE);
7056 /* if the operand is already in dptr
7057 then we do nothing else we move the value to dptr */
7058 if (AOP_TYPE (left) != AOP_STR)
7060 /* if this is remateriazable */
7061 if (AOP_TYPE (left) == AOP_IMMD)
7062 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7064 { /* we need to get it byte by byte */
7065 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7066 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7069 /* so dptr know contains the address */
7070 aopOp (result, ic, FALSE);
7072 /* if bit then unpack */
7073 if (IS_BITVAR (retype))
7074 genUnpackBits (result, "dptr", FPOINTER);
7077 size = AOP_SIZE (result);
7082 emitcode ("movx", "a,@dptr");
7083 aopPut (AOP (result), "a", offset++);
7085 emitcode ("inc", "dptr");
7089 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7090 aopPut ( AOP (left), "dpl", 0);
7091 aopPut ( AOP (left), "dph", 1);
7094 freeAsmop (left, NULL, ic, TRUE);
7095 freeAsmop (result, NULL, ic, TRUE);
7098 /*-----------------------------------------------------------------*/
7099 /* genCodePointerGet - gget value from code space */
7100 /*-----------------------------------------------------------------*/
7102 genCodePointerGet (operand * left,
7103 operand * result, iCode * ic, iCode *pi)
7106 sym_link *retype = getSpec (operandType (result));
7108 aopOp (left, ic, FALSE);
7110 /* if the operand is already in dptr
7111 then we do nothing else we move the value to dptr */
7112 if (AOP_TYPE (left) != AOP_STR)
7114 /* if this is remateriazable */
7115 if (AOP_TYPE (left) == AOP_IMMD)
7116 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7118 { /* we need to get it byte by byte */
7119 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7120 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7123 /* so dptr know contains the address */
7124 aopOp (result, ic, FALSE);
7126 /* if bit then unpack */
7127 if (IS_BITVAR (retype))
7128 genUnpackBits (result, "dptr", CPOINTER);
7131 size = AOP_SIZE (result);
7136 emitcode ("clr", "a");
7137 emitcode ("movc", "a,@a+dptr");
7138 aopPut (AOP (result), "a", offset++);
7140 emitcode ("inc", "dptr");
7144 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7145 aopPut ( AOP (left), "dpl", 0);
7146 aopPut ( AOP (left), "dph", 1);
7149 freeAsmop (left, NULL, ic, TRUE);
7150 freeAsmop (result, NULL, ic, TRUE);
7153 /*-----------------------------------------------------------------*/
7154 /* genGenPointerGet - gget value from generic pointer space */
7155 /*-----------------------------------------------------------------*/
7157 genGenPointerGet (operand * left,
7158 operand * result, iCode * ic, iCode *pi)
7161 sym_link *retype = getSpec (operandType (result));
7163 aopOp (left, ic, FALSE);
7165 /* if the operand is already in dptr
7166 then we do nothing else we move the value to dptr */
7167 if (AOP_TYPE (left) != AOP_STR)
7169 /* if this is remateriazable */
7170 if (AOP_TYPE (left) == AOP_IMMD)
7172 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7173 emitcode ("mov", "b,#%d", pointerCode (retype));
7176 { /* we need to get it byte by byte */
7177 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7178 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7179 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7182 /* so dptr know contains the address */
7183 aopOp (result, ic, FALSE);
7185 /* if bit then unpack */
7186 if (IS_BITVAR (retype))
7187 genUnpackBits (result, "dptr", GPOINTER);
7190 size = AOP_SIZE (result);
7195 emitcode ("lcall", "__gptrget");
7196 aopPut (AOP (result), "a", offset++);
7198 emitcode ("inc", "dptr");
7202 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7203 aopPut ( AOP (left), "dpl", 0);
7204 aopPut ( AOP (left), "dph", 1);
7207 freeAsmop (left, NULL, ic, TRUE);
7208 freeAsmop (result, NULL, ic, TRUE);
7211 /*-----------------------------------------------------------------*/
7212 /* genPointerGet - generate code for pointer get */
7213 /*-----------------------------------------------------------------*/
7215 genPointerGet (iCode * ic, iCode *pi)
7217 operand *left, *result;
7218 sym_link *type, *etype;
7221 left = IC_LEFT (ic);
7222 result = IC_RESULT (ic);
7224 /* depending on the type of pointer we need to
7225 move it to the correct pointer register */
7226 type = operandType (left);
7227 etype = getSpec (type);
7228 /* if left is of type of pointer then it is simple */
7229 if (IS_PTR (type) && !IS_FUNC (type->next))
7230 p_type = DCL_TYPE (type);
7233 /* we have to go by the storage class */
7234 p_type = PTR_TYPE (SPEC_OCLS (etype));
7237 /* now that we have the pointer type we assign
7238 the pointer values */
7244 genNearPointerGet (left, result, ic, pi);
7248 genPagedPointerGet (left, result, ic, pi);
7252 genFarPointerGet (left, result, ic, pi);
7256 genCodePointerGet (left, result, ic, pi);
7260 genGenPointerGet (left, result, ic, pi);
7266 /*-----------------------------------------------------------------*/
7267 /* genPackBits - generates code for packed bit storage */
7268 /*-----------------------------------------------------------------*/
7270 genPackBits (sym_link * etype,
7272 char *rname, int p_type)
7280 blen = SPEC_BLEN (etype);
7281 bstr = SPEC_BSTR (etype);
7283 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7286 /* if the bit lenth is less than or */
7287 /* it exactly fits a byte then */
7288 if (SPEC_BLEN (etype) <= 8)
7290 shCount = SPEC_BSTR (etype);
7292 /* shift left acc */
7295 if (SPEC_BLEN (etype) < 8)
7296 { /* if smaller than a byte */
7302 emitcode ("mov", "b,a");
7303 emitcode ("mov", "a,@%s", rname);
7307 emitcode ("mov", "b,a");
7308 emitcode ("movx", "a,@dptr");
7312 emitcode ("push", "b");
7313 emitcode ("push", "acc");
7314 emitcode ("lcall", "__gptrget");
7315 emitcode ("pop", "b");
7319 emitcode ("anl", "a,#0x%02x", (unsigned char)
7320 ((unsigned char) (0xFF << (blen + bstr)) |
7321 (unsigned char) (0xFF >> (8 - bstr))));
7322 emitcode ("orl", "a,b");
7323 if (p_type == GPOINTER)
7324 emitcode ("pop", "b");
7331 emitcode ("mov", "@%s,a", rname);
7335 emitcode ("movx", "@dptr,a");
7339 emitcode ("lcall", "__gptrput");
7344 if (SPEC_BLEN (etype) <= 8)
7347 emitcode ("inc", "%s", rname);
7348 rLen = SPEC_BLEN (etype);
7350 /* now generate for lengths greater than one byte */
7354 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7366 emitcode ("mov", "@%s,a", rname);
7369 emitcode ("mov", "@%s,%s", rname, l);
7374 emitcode ("movx", "@dptr,a");
7379 emitcode ("lcall", "__gptrput");
7382 emitcode ("inc", "%s", rname);
7387 /* last last was not complete */
7390 /* save the byte & read byte */
7394 emitcode ("mov", "b,a");
7395 emitcode ("mov", "a,@%s", rname);
7399 emitcode ("mov", "b,a");
7400 emitcode ("movx", "a,@dptr");
7404 emitcode ("push", "b");
7405 emitcode ("push", "acc");
7406 emitcode ("lcall", "__gptrget");
7407 emitcode ("pop", "b");
7411 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7412 emitcode ("orl", "a,b");
7415 if (p_type == GPOINTER)
7416 emitcode ("pop", "b");
7422 emitcode ("mov", "@%s,a", rname);
7426 emitcode ("movx", "@dptr,a");
7430 emitcode ("lcall", "__gptrput");
7434 /*-----------------------------------------------------------------*/
7435 /* genDataPointerSet - remat pointer to data space */
7436 /*-----------------------------------------------------------------*/
7438 genDataPointerSet (operand * right,
7442 int size, offset = 0;
7443 char *l, buffer[256];
7445 aopOp (right, ic, FALSE);
7447 l = aopGet (AOP (result), 0, FALSE, TRUE);
7448 size = AOP_SIZE (right);
7452 sprintf (buffer, "(%s + %d)", l + 1, offset);
7454 sprintf (buffer, "%s", l + 1);
7455 emitcode ("mov", "%s,%s", buffer,
7456 aopGet (AOP (right), offset++, FALSE, FALSE));
7459 freeAsmop (right, NULL, ic, TRUE);
7460 freeAsmop (result, NULL, ic, TRUE);
7463 /*-----------------------------------------------------------------*/
7464 /* genNearPointerSet - emitcode for near pointer put */
7465 /*-----------------------------------------------------------------*/
7467 genNearPointerSet (operand * right,
7475 sym_link *retype, *letype;
7476 sym_link *ptype = operandType (result);
7478 retype = getSpec (operandType (right));
7479 letype = getSpec (ptype);
7480 aopOp (result, ic, FALSE);
7482 /* if the result is rematerializable &
7483 in data space & not a bit variable */
7484 if (AOP_TYPE (result) == AOP_IMMD &&
7485 DCL_TYPE (ptype) == POINTER &&
7486 !IS_BITVAR (retype) &&
7487 !IS_BITVAR (letype))
7489 genDataPointerSet (right, result, ic);
7493 /* if the value is already in a pointer register
7494 then don't need anything more */
7495 if (!AOP_INPREG (AOP (result)))
7497 /* otherwise get a free pointer register */
7499 preg = getFreePtr (ic, &aop, FALSE);
7500 emitcode ("mov", "%s,%s",
7502 aopGet (AOP (result), 0, FALSE, TRUE));
7506 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7508 aopOp (right, ic, FALSE);
7510 /* if bitfield then unpack the bits */
7511 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7512 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7515 /* we have can just get the values */
7516 int size = AOP_SIZE (right);
7521 l = aopGet (AOP (right), offset, FALSE, TRUE);
7525 emitcode ("mov", "@%s,a", rname);
7528 emitcode ("mov", "@%s,%s", rname, l);
7530 emitcode ("inc", "%s", rname);
7535 /* now some housekeeping stuff */
7536 if (aop) /* we had to allocate for this iCode */
7538 if (pi) aopPut (AOP (result),rname,0);
7539 freeAsmop (NULL, aop, ic, TRUE);
7543 /* we did not allocate which means left
7544 already in a pointer register, then
7545 if size > 0 && this could be used again
7546 we have to point it back to where it
7548 if ((AOP_SIZE (right) > 1 &&
7549 !OP_SYMBOL (result)->remat &&
7550 (OP_SYMBOL (result)->liveTo > ic->seq ||
7554 int size = AOP_SIZE (right) - 1;
7556 emitcode ("dec", "%s", rname);
7561 if (pi) pi->generated = 1;
7562 freeAsmop (result, NULL, ic, TRUE);
7563 freeAsmop (right, NULL, ic, TRUE);
7566 /*-----------------------------------------------------------------*/
7567 /* genPagedPointerSet - emitcode for Paged pointer put */
7568 /*-----------------------------------------------------------------*/
7570 genPagedPointerSet (operand * right,
7578 sym_link *retype, *letype;
7580 retype = getSpec (operandType (right));
7581 letype = getSpec (operandType (result));
7583 aopOp (result, ic, FALSE);
7585 /* if the value is already in a pointer register
7586 then don't need anything more */
7587 if (!AOP_INPREG (AOP (result)))
7589 /* otherwise get a free pointer register */
7591 preg = getFreePtr (ic, &aop, FALSE);
7592 emitcode ("mov", "%s,%s",
7594 aopGet (AOP (result), 0, FALSE, TRUE));
7598 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7600 aopOp (right, ic, FALSE);
7602 /* if bitfield then unpack the bits */
7603 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7604 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7607 /* we have can just get the values */
7608 int size = AOP_SIZE (right);
7613 l = aopGet (AOP (right), offset, FALSE, TRUE);
7616 emitcode ("movx", "@%s,a", rname);
7619 emitcode ("inc", "%s", rname);
7625 /* now some housekeeping stuff */
7626 if (aop) /* we had to allocate for this iCode */
7628 if (pi) aopPut (AOP (result),rname,0);
7629 freeAsmop (NULL, aop, ic, TRUE);
7633 /* we did not allocate which means left
7634 already in a pointer register, then
7635 if size > 0 && this could be used again
7636 we have to point it back to where it
7638 if (AOP_SIZE (right) > 1 &&
7639 !OP_SYMBOL (result)->remat &&
7640 (OP_SYMBOL (result)->liveTo > ic->seq ||
7643 int size = AOP_SIZE (right) - 1;
7645 emitcode ("dec", "%s", rname);
7650 if (pi) pi->generated = 1;
7651 freeAsmop (result, NULL, ic, TRUE);
7652 freeAsmop (right, NULL, ic, TRUE);
7657 /*-----------------------------------------------------------------*/
7658 /* genFarPointerSet - set value from far space */
7659 /*-----------------------------------------------------------------*/
7661 genFarPointerSet (operand * right,
7662 operand * result, iCode * ic, iCode * pi)
7665 sym_link *retype = getSpec (operandType (right));
7666 sym_link *letype = getSpec (operandType (result));
7667 aopOp (result, ic, FALSE);
7669 /* if the operand is already in dptr
7670 then we do nothing else we move the value to dptr */
7671 if (AOP_TYPE (result) != AOP_STR)
7673 /* if this is remateriazable */
7674 if (AOP_TYPE (result) == AOP_IMMD)
7675 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7677 { /* we need to get it byte by byte */
7678 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7679 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7682 /* so dptr know contains the address */
7683 aopOp (right, ic, FALSE);
7685 /* if bit then unpack */
7686 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7687 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7690 size = AOP_SIZE (right);
7695 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7697 emitcode ("movx", "@dptr,a");
7699 emitcode ("inc", "dptr");
7702 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7703 aopPut (AOP(result),"dpl",0);
7704 aopPut (AOP(result),"dph",1);
7707 freeAsmop (result, NULL, ic, TRUE);
7708 freeAsmop (right, NULL, ic, TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genGenPointerSet - set value from generic pointer space */
7713 /*-----------------------------------------------------------------*/
7715 genGenPointerSet (operand * right,
7716 operand * result, iCode * ic, iCode * pi)
7719 sym_link *retype = getSpec (operandType (right));
7720 sym_link *letype = getSpec (operandType (result));
7722 aopOp (result, ic, FALSE);
7724 /* if the operand is already in dptr
7725 then we do nothing else we move the value to dptr */
7726 if (AOP_TYPE (result) != AOP_STR)
7728 /* if this is remateriazable */
7729 if (AOP_TYPE (result) == AOP_IMMD)
7731 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7732 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7735 { /* we need to get it byte by byte */
7736 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7737 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7738 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7741 /* so dptr know contains the address */
7742 aopOp (right, ic, FALSE);
7744 /* if bit then unpack */
7745 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7746 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7749 size = AOP_SIZE (right);
7754 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7756 emitcode ("lcall", "__gptrput");
7758 emitcode ("inc", "dptr");
7762 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7763 aopPut (AOP(result),"dpl",0);
7764 aopPut (AOP(result),"dph",1);
7767 freeAsmop (result, NULL, ic, TRUE);
7768 freeAsmop (right, NULL, ic, TRUE);
7771 /*-----------------------------------------------------------------*/
7772 /* genPointerSet - stores the value into a pointer location */
7773 /*-----------------------------------------------------------------*/
7775 genPointerSet (iCode * ic, iCode *pi)
7777 operand *right, *result;
7778 sym_link *type, *etype;
7781 right = IC_RIGHT (ic);
7782 result = IC_RESULT (ic);
7784 /* depending on the type of pointer we need to
7785 move it to the correct pointer register */
7786 type = operandType (result);
7787 etype = getSpec (type);
7788 /* if left is of type of pointer then it is simple */
7789 if (IS_PTR (type) && !IS_FUNC (type->next))
7791 p_type = DCL_TYPE (type);
7795 /* we have to go by the storage class */
7796 p_type = PTR_TYPE (SPEC_OCLS (etype));
7799 /* now that we have the pointer type we assign
7800 the pointer values */
7806 genNearPointerSet (right, result, ic, pi);
7810 genPagedPointerSet (right, result, ic, pi);
7814 genFarPointerSet (right, result, ic, pi);
7818 genGenPointerSet (right, result, ic, pi);
7824 /*-----------------------------------------------------------------*/
7825 /* genIfx - generate code for Ifx statement */
7826 /*-----------------------------------------------------------------*/
7828 genIfx (iCode * ic, iCode * popIc)
7830 operand *cond = IC_COND (ic);
7833 aopOp (cond, ic, FALSE);
7835 /* get the value into acc */
7836 if (AOP_TYPE (cond) != AOP_CRY)
7840 /* the result is now in the accumulator */
7841 freeAsmop (cond, NULL, ic, TRUE);
7843 /* if there was something to be popped then do it */
7847 /* if the condition is a bit variable */
7848 if (isbit && IS_ITEMP (cond) &&
7850 genIfxJump (ic, SPIL_LOC (cond)->rname);
7851 else if (isbit && !IS_ITEMP (cond))
7852 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7854 genIfxJump (ic, "a");
7859 /*-----------------------------------------------------------------*/
7860 /* genAddrOf - generates code for address of */
7861 /*-----------------------------------------------------------------*/
7863 genAddrOf (iCode * ic)
7865 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7868 aopOp (IC_RESULT (ic), ic, FALSE);
7870 /* if the operand is on the stack then we
7871 need to get the stack offset of this
7875 /* if it has an offset then we need to compute
7879 emitcode ("mov", "a,_bp");
7880 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7881 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7885 /* we can just move _bp */
7886 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7888 /* fill the result with zero */
7889 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7894 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7900 /* object not on stack then we need the name */
7901 size = AOP_SIZE (IC_RESULT (ic));
7906 char s[SDCC_NAME_MAX];
7908 sprintf (s, "#(%s >> %d)",
7912 sprintf (s, "#%s", sym->rname);
7913 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7917 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7921 /*-----------------------------------------------------------------*/
7922 /* genFarFarAssign - assignment when both are in far space */
7923 /*-----------------------------------------------------------------*/
7925 genFarFarAssign (operand * result, operand * right, iCode * ic)
7927 int size = AOP_SIZE (right);
7930 /* first push the right side on to the stack */
7933 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7935 emitcode ("push", "acc");
7938 freeAsmop (right, NULL, ic, FALSE);
7939 /* now assign DPTR to result */
7940 aopOp (result, ic, FALSE);
7941 size = AOP_SIZE (result);
7944 emitcode ("pop", "acc");
7945 aopPut (AOP (result), "a", --offset);
7947 freeAsmop (result, NULL, ic, FALSE);
7951 /*-----------------------------------------------------------------*/
7952 /* genAssign - generate code for assignment */
7953 /*-----------------------------------------------------------------*/
7955 genAssign (iCode * ic)
7957 operand *result, *right;
7959 unsigned long lit = 0L;
7961 result = IC_RESULT (ic);
7962 right = IC_RIGHT (ic);
7964 /* if they are the same */
7965 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7968 aopOp (right, ic, FALSE);
7970 /* special case both in far space */
7971 if (AOP_TYPE (right) == AOP_DPTR &&
7972 IS_TRUE_SYMOP (result) &&
7973 isOperandInFarSpace (result))
7976 genFarFarAssign (result, right, ic);
7980 aopOp (result, ic, TRUE);
7982 /* if they are the same registers */
7983 if (sameRegs (AOP (right), AOP (result)))
7986 /* if the result is a bit */
7987 if (AOP_TYPE (result) == AOP_CRY)
7990 /* if the right size is a literal then
7991 we know what the value is */
7992 if (AOP_TYPE (right) == AOP_LIT)
7994 if (((int) operandLitValue (right)))
7995 aopPut (AOP (result), one, 0);
7997 aopPut (AOP (result), zero, 0);
8001 /* the right is also a bit variable */
8002 if (AOP_TYPE (right) == AOP_CRY)
8004 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8005 aopPut (AOP (result), "c", 0);
8011 aopPut (AOP (result), "a", 0);
8015 /* bit variables done */
8017 size = AOP_SIZE (result);
8019 if (AOP_TYPE (right) == AOP_LIT)
8020 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8022 (AOP_TYPE (result) != AOP_REG) &&
8023 (AOP_TYPE (right) == AOP_LIT) &&
8024 !IS_FLOAT (operandType (right)) &&
8027 emitcode ("clr", "a");
8030 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8031 aopPut (AOP (result), "a", size);
8033 aopPut (AOP (result),
8034 aopGet (AOP (right), size, FALSE, FALSE),
8042 aopPut (AOP (result),
8043 aopGet (AOP (right), offset, FALSE, FALSE),
8050 freeAsmop (right, NULL, ic, TRUE);
8051 freeAsmop (result, NULL, ic, TRUE);
8054 /*-----------------------------------------------------------------*/
8055 /* genJumpTab - genrates code for jump table */
8056 /*-----------------------------------------------------------------*/
8058 genJumpTab (iCode * ic)
8063 aopOp (IC_JTCOND (ic), ic, FALSE);
8064 /* get the condition into accumulator */
8065 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8067 /* multiply by three */
8068 emitcode ("add", "a,acc");
8069 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8070 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8072 jtab = newiTempLabel (NULL);
8073 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8074 emitcode ("jmp", "@a+dptr");
8075 emitcode ("", "%05d$:", jtab->key + 100);
8076 /* now generate the jump labels */
8077 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8078 jtab = setNextItem (IC_JTLABELS (ic)))
8079 emitcode ("ljmp", "%05d$", jtab->key + 100);
8083 /*-----------------------------------------------------------------*/
8084 /* genCast - gen code for casting */
8085 /*-----------------------------------------------------------------*/
8087 genCast (iCode * ic)
8089 operand *result = IC_RESULT (ic);
8090 sym_link *ctype = operandType (IC_LEFT (ic));
8091 sym_link *rtype = operandType (IC_RIGHT (ic));
8092 operand *right = IC_RIGHT (ic);
8095 /* if they are equivalent then do nothing */
8096 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8099 aopOp (right, ic, FALSE);
8100 aopOp (result, ic, FALSE);
8102 /* if the result is a bit */
8103 if (AOP_TYPE (result) == AOP_CRY)
8105 /* if the right size is a literal then
8106 we know what the value is */
8107 if (AOP_TYPE (right) == AOP_LIT)
8109 if (((int) operandLitValue (right)))
8110 aopPut (AOP (result), one, 0);
8112 aopPut (AOP (result), zero, 0);
8117 /* the right is also a bit variable */
8118 if (AOP_TYPE (right) == AOP_CRY)
8120 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8121 aopPut (AOP (result), "c", 0);
8127 aopPut (AOP (result), "a", 0);
8131 /* if they are the same size : or less */
8132 if (AOP_SIZE (result) <= AOP_SIZE (right))
8135 /* if they are in the same place */
8136 if (sameRegs (AOP (right), AOP (result)))
8139 /* if they in different places then copy */
8140 size = AOP_SIZE (result);
8144 aopPut (AOP (result),
8145 aopGet (AOP (right), offset, FALSE, FALSE),
8153 /* if the result is of type pointer */
8158 sym_link *type = operandType (right);
8159 sym_link *etype = getSpec (type);
8161 /* pointer to generic pointer */
8162 if (IS_GENPTR (ctype))
8167 p_type = DCL_TYPE (type);
8170 /* we have to go by the storage class */
8171 p_type = PTR_TYPE (SPEC_OCLS (etype));
8174 /* the first two bytes are known */
8175 size = GPTRSIZE - 1;
8179 aopPut (AOP (result),
8180 aopGet (AOP (right), offset, FALSE, FALSE),
8184 /* the last byte depending on type */
8202 /* this should never happen */
8203 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8204 "got unknown pointer type");
8207 aopPut (AOP (result), l, GPTRSIZE - 1);
8211 /* just copy the pointers */
8212 size = AOP_SIZE (result);
8216 aopPut (AOP (result),
8217 aopGet (AOP (right), offset, FALSE, FALSE),
8224 /* so we now know that the size of destination is greater
8225 than the size of the source */
8226 /* we move to result for the size of source */
8227 size = AOP_SIZE (right);
8231 aopPut (AOP (result),
8232 aopGet (AOP (right), offset, FALSE, FALSE),
8237 /* now depending on the sign of the source && destination */
8238 size = AOP_SIZE (result) - AOP_SIZE (right);
8239 /* if unsigned or not an integral type */
8240 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8243 aopPut (AOP (result), zero, offset++);
8247 /* we need to extend the sign :{ */
8248 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8251 emitcode ("rlc", "a");
8252 emitcode ("subb", "a,acc");
8254 aopPut (AOP (result), "a", offset++);
8257 /* we are done hurray !!!! */
8260 freeAsmop (right, NULL, ic, TRUE);
8261 freeAsmop (result, NULL, ic, TRUE);
8265 /*-----------------------------------------------------------------*/
8266 /* genDjnz - generate decrement & jump if not zero instrucion */
8267 /*-----------------------------------------------------------------*/
8269 genDjnz (iCode * ic, iCode * ifx)
8275 /* if the if condition has a false label
8276 then we cannot save */
8280 /* if the minus is not of the form
8282 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8283 !IS_OP_LITERAL (IC_RIGHT (ic)))
8286 if (operandLitValue (IC_RIGHT (ic)) != 1)
8289 /* if the size of this greater than one then no
8291 if (getSize (operandType (IC_RESULT (ic))) > 1)
8294 /* otherwise we can save BIG */
8295 lbl = newiTempLabel (NULL);
8296 lbl1 = newiTempLabel (NULL);
8298 aopOp (IC_RESULT (ic), ic, FALSE);
8300 if (AOP_NEEDSACC(IC_RESULT(ic)))
8302 /* If the result is accessed indirectly via
8303 * the accumulator, we must explicitly write
8304 * it back after the decrement.
8306 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8308 if (strcmp(rByte, "a"))
8310 /* Something is hopelessly wrong */
8311 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8312 __FILE__, __LINE__);
8313 /* We can just give up; the generated code will be inefficient,
8316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8319 emitcode ("dec", "%s", rByte);
8320 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8321 emitcode ("jnz", "%05d$", lbl->key + 100);
8323 else if (IS_AOP_PREG (IC_RESULT (ic)))
8325 emitcode ("dec", "%s",
8326 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8327 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8328 emitcode ("jnz", "%05d$", lbl->key + 100);
8332 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8335 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8336 emitcode ("", "%05d$:", lbl->key + 100);
8337 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8338 emitcode ("", "%05d$:", lbl1->key + 100);
8340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8345 /*-----------------------------------------------------------------*/
8346 /* genReceive - generate code for a receive iCode */
8347 /*-----------------------------------------------------------------*/
8349 genReceive (iCode * ic)
8351 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8352 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8353 IS_TRUE_SYMOP (IC_RESULT (ic))))
8356 int size = getSize (operandType (IC_RESULT (ic)));
8357 int offset = fReturnSizeMCS51 - size;
8360 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8361 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8364 aopOp (IC_RESULT (ic), ic, FALSE);
8365 size = AOP_SIZE (IC_RESULT (ic));
8369 emitcode ("pop", "acc");
8370 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8377 aopOp (IC_RESULT (ic), ic, FALSE);
8379 assignResultValue (IC_RESULT (ic));
8382 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8385 /*-----------------------------------------------------------------*/
8386 /* gen51Code - generate code for 8051 based controllers */
8387 /*-----------------------------------------------------------------*/
8389 gen51Code (iCode * lic)
8394 lineHead = lineCurr = NULL;
8396 /* print the allocation information */
8398 printAllocInfo (currFunc, codeOutFile);
8399 /* if debug information required */
8400 /* if (options.debug && currFunc) { */
8403 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8405 if (IS_STATIC (currFunc->etype))
8406 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8408 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8411 /* stack pointer name */
8412 if (options.useXstack)
8418 for (ic = lic; ic; ic = ic->next)
8421 if (cln != ic->lineno)
8426 emitcode ("", "C$%s$%d$%d$%d ==.",
8427 FileBaseName (ic->filename), ic->lineno,
8428 ic->level, ic->block);
8431 emitcode (";", "%s %d", ic->filename, ic->lineno);
8434 /* if the result is marked as
8435 spilt and rematerializable or code for
8436 this has already been generated then
8438 if (resultRemat (ic) || ic->generated)
8441 /* depending on the operation */
8461 /* IPOP happens only when trying to restore a
8462 spilt live range, if there is an ifx statement
8463 following this pop then the if statement might
8464 be using some of the registers being popped which
8465 would destory the contents of the register so
8466 we need to check for this condition and handle it */
8468 ic->next->op == IFX &&
8469 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8470 genIfx (ic->next, ic);
8488 genEndFunction (ic);
8508 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8525 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8529 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8536 /* note these two are xlated by algebraic equivalence
8537 during parsing SDCC.y */
8538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8539 "got '>=' or '<=' shouldn't have come here");
8543 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8555 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8559 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8563 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8590 case GET_VALUE_AT_ADDRESS:
8591 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8595 if (POINTER_SET (ic))
8596 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8622 addSet (&_G.sendSet, ic);
8631 /* now we are ready to call the
8632 peep hole optimizer */
8633 if (!options.nopeep)
8634 peepHole (&lineHead);
8636 /* now do the actual printing */
8637 printLine (lineHead, codeOutFile);