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) && !defined(__MINGW32__)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[INITIAL_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 mcs51_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 mcs51_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return mcs51_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
236 /* other wise this is true end of the world */
237 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
238 "getFreePtr should never reach here");
242 /*-----------------------------------------------------------------*/
243 /* newAsmop - creates a new asmOp */
244 /*-----------------------------------------------------------------*/
246 newAsmop (short type)
250 aop = Safe_calloc (1, sizeof (asmop));
255 /*-----------------------------------------------------------------*/
256 /* pointerCode - returns the code for a pointer type */
257 /*-----------------------------------------------------------------*/
259 pointerCode (sym_link * etype)
262 return PTR_TYPE (SPEC_OCLS (etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
270 aopForSym (iCode * ic, symbol * sym, bool result)
273 memmap *space = SPEC_OCLS (sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if (sym->onStack || sym->iaccess)
284 sym->aop = aop = newAsmop (0);
285 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
286 aop->size = getSize (sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK)
296 emitcode ("push", "acc");
298 emitcode ("mov", "a,_bp");
299 emitcode ("add", "a,#0x%02x",
301 ((char) (sym->stack - _G.nRegsSaved)) :
302 ((char) sym->stack)) & 0xff);
303 emitcode ("mov", "%s,a",
304 aop->aopu.aop_ptr->name);
307 emitcode ("pop", "acc");
310 emitcode ("mov", "%s,#%s",
311 aop->aopu.aop_ptr->name,
313 aop->paged = space->paged;
316 aop->aopu.aop_stk = sym->stack;
320 /* if in bit space */
321 if (IN_BITSPACE (space))
323 sym->aop = aop = newAsmop (AOP_CRY);
324 aop->aopu.aop_dir = sym->rname;
325 aop->size = getSize (sym->type);
328 /* if it is in direct space */
329 if (IN_DIRSPACE (space))
331 sym->aop = aop = newAsmop (AOP_DIR);
332 aop->aopu.aop_dir = sym->rname;
333 aop->size = getSize (sym->type);
337 /* special case for a function */
338 if (IS_FUNC (sym->type))
340 sym->aop = aop = newAsmop (AOP_IMMD);
341 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
342 strcpy (aop->aopu.aop_immd, sym->rname);
343 aop->size = FPTRSIZE;
347 /* only remaining is far space */
348 /* in which case DPTR gets the address */
349 sym->aop = aop = newAsmop (AOP_DPTR);
350 emitcode ("mov", "dptr,#%s", sym->rname);
351 aop->size = getSize (sym->type);
353 /* if it is in code space */
354 if (IN_CODESPACE (space))
360 /*-----------------------------------------------------------------*/
361 /* aopForRemat - rematerialzes an object */
362 /*-----------------------------------------------------------------*/
364 aopForRemat (symbol * sym)
366 iCode *ic = sym->rematiCode;
367 asmop *aop = newAsmop (AOP_IMMD);
373 val += (int) operandLitValue (IC_RIGHT (ic));
374 else if (ic->op == '-')
375 val -= (int) operandLitValue (IC_RIGHT (ic));
379 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
383 sprintf (buffer, "(%s %c 0x%04x)",
384 OP_SYMBOL (IC_LEFT (ic))->rname,
385 val >= 0 ? '+' : '-',
388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
390 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
391 strcpy (aop->aopu.aop_immd, buffer);
395 /*-----------------------------------------------------------------*/
396 /* regsInCommon - two operands have some registers in common */
397 /*-----------------------------------------------------------------*/
399 regsInCommon (operand * op1, operand * op2)
404 /* if they have registers in common */
405 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
408 sym1 = OP_SYMBOL (op1);
409 sym2 = OP_SYMBOL (op2);
411 if (sym1->nRegs == 0 || sym2->nRegs == 0)
414 for (i = 0; i < sym1->nRegs; i++)
420 for (j = 0; j < sym2->nRegs; j++)
425 if (sym2->regs[j] == sym1->regs[i])
433 /*-----------------------------------------------------------------*/
434 /* operandsEqu - equivalent */
435 /*-----------------------------------------------------------------*/
437 operandsEqu (operand * op1, operand * op2)
441 /* if they not symbols */
442 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
445 sym1 = OP_SYMBOL (op1);
446 sym2 = OP_SYMBOL (op2);
448 /* if both are itemps & one is spilt
449 and the other is not then false */
450 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
451 sym1->isspilt != sym2->isspilt)
454 /* if they are the same */
458 if (strcmp (sym1->rname, sym2->rname) == 0)
462 /* if left is a tmp & right is not */
463 if (IS_ITEMP (op1) &&
466 (sym1->usl.spillLoc == sym2))
469 if (IS_ITEMP (op2) &&
473 (sym2->usl.spillLoc == sym1))
479 /*-----------------------------------------------------------------*/
480 /* sameRegs - two asmops have the same registers */
481 /*-----------------------------------------------------------------*/
483 sameRegs (asmop * aop1, asmop * aop2)
490 if (aop1->type != AOP_REG ||
491 aop2->type != AOP_REG)
494 if (aop1->size != aop2->size)
497 for (i = 0; i < aop1->size; i++)
498 if (aop1->aopu.aop_reg[i] !=
499 aop2->aopu.aop_reg[i])
505 /*-----------------------------------------------------------------*/
506 /* aopOp - allocates an asmop for an operand : */
507 /*-----------------------------------------------------------------*/
509 aopOp (operand * op, iCode * ic, bool result)
518 /* if this a literal */
519 if (IS_OP_LITERAL (op))
521 op->aop = aop = newAsmop (AOP_LIT);
522 aop->aopu.aop_lit = op->operand.valOperand;
523 aop->size = getSize (operandType (op));
527 /* if already has a asmop then continue */
531 /* if the underlying symbol has a aop */
532 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
534 op->aop = OP_SYMBOL (op)->aop;
538 /* if this is a true symbol */
539 if (IS_TRUE_SYMOP (op))
541 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
545 /* this is a temporary : this has
551 e) can be a return use only */
553 sym = OP_SYMBOL (op);
556 /* if the type is a conditional */
557 if (sym->regType == REG_CND)
559 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
564 /* if it is spilt then two situations
566 b) has a spill location */
567 if (sym->isspilt || sym->nRegs == 0)
570 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize (sym->type);
582 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
583 aop->size = getSize (sym->type);
584 for (i = 0; i < 2; i++)
585 aop->aopu.aop_str[i] = accUse[i];
592 aop = op->aop = sym->aop = newAsmop (AOP_STR);
593 aop->size = getSize (sym->type);
594 for (i = 0; i < fReturnSizeMCS51; i++)
595 aop->aopu.aop_str[i] = fReturn[i];
599 /* else spill location */
600 sym->aop = op->aop = aop =
601 aopForSym (ic, sym->usl.spillLoc, result);
602 aop->size = getSize (sym->type);
606 /* must be in a register */
607 sym->aop = op->aop = aop = newAsmop (AOP_REG);
608 aop->size = sym->nRegs;
609 for (i = 0; i < sym->nRegs; i++)
610 aop->aopu.aop_reg[i] = sym->regs[i];
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand */
615 /*----------------------------------------------------------------*/
617 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
634 /* depending on the asmop type only three cases need work AOP_RO
635 , AOP_R1 && AOP_STK */
643 emitcode ("pop", "ar0");
647 bitVectUnSetBit (ic->rUsed, R0_IDX);
655 emitcode ("pop", "ar1");
659 bitVectUnSetBit (ic->rUsed, R1_IDX);
665 int stk = aop->aopu.aop_stk + aop->size;
666 bitVectUnSetBit (ic->rUsed, R0_IDX);
667 bitVectUnSetBit (ic->rUsed, R1_IDX);
669 getFreePtr (ic, &aop, FALSE);
673 emitcode ("mov", "a,_bp");
674 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
675 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
679 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
684 emitcode ("pop", "acc");
685 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
688 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
691 freeAsmop (op, NULL, ic, TRUE);
694 emitcode ("pop", "ar0");
700 emitcode ("pop", "ar1");
707 /* all other cases just dealloc */
713 OP_SYMBOL (op)->aop = NULL;
714 /* if the symbol has a spill */
716 SPIL_LOC (op)->aop = NULL;
721 /*-----------------------------------------------------------------*/
722 /* aopGet - for fetching value of the aop */
723 /*-----------------------------------------------------------------*/
725 aopGet (asmop * aop, int offset, bool bit16, bool dname)
730 /* offset is greater than
732 if (offset > (aop->size - 1) &&
733 aop->type != AOP_LIT)
736 /* depending on type */
742 /* if we need to increment it */
743 while (offset > aop->coff)
745 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
749 while (offset < aop->coff)
751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
758 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
759 return (dname ? "acc" : "a");
761 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
762 rs = Safe_calloc (1, strlen (s) + 1);
767 while (offset > aop->coff)
769 emitcode ("inc", "dptr");
773 while (offset < aop->coff)
775 emitcode ("lcall", "__decdptr");
782 emitcode ("clr", "a");
783 emitcode ("movc", "a,@a+dptr");
787 emitcode ("movx", "a,@dptr");
789 return (dname ? "acc" : "a");
794 sprintf (s, "#%s", aop->aopu.aop_immd);
796 sprintf (s, "#(%s >> %d)",
802 rs = Safe_calloc (1, strlen (s) + 1);
808 sprintf (s, "(%s + %d)",
812 sprintf (s, "%s", aop->aopu.aop_dir);
813 rs = Safe_calloc (1, strlen (s) + 1);
819 return aop->aopu.aop_reg[offset]->dname;
821 return aop->aopu.aop_reg[offset]->name;
824 emitcode ("clr", "a");
825 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
826 emitcode ("rlc", "a");
827 return (dname ? "acc" : "a");
830 if (!offset && dname)
832 return aop->aopu.aop_str[offset];
835 return aopLiteral (aop->aopu.aop_lit, offset);
839 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
843 return aop->aopu.aop_str[offset];
847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
848 "aopget got unsupported aop->type");
851 /*-----------------------------------------------------------------*/
852 /* aopPut - puts a string for a aop */
853 /*-----------------------------------------------------------------*/
855 aopPut (asmop * aop, char *s, int offset)
859 if (aop->size && offset > (aop->size - 1))
861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
862 "aopPut got offset > aop->size");
866 /* will assign value to value */
867 /* depending on where it is ofcourse */
872 sprintf (d, "(%s + %d)",
873 aop->aopu.aop_dir, offset);
875 sprintf (d, "%s", aop->aopu.aop_dir);
878 emitcode ("mov", "%s,%s", d, s);
883 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
884 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
887 strcmp (s, "r0") == 0 ||
888 strcmp (s, "r1") == 0 ||
889 strcmp (s, "r2") == 0 ||
890 strcmp (s, "r3") == 0 ||
891 strcmp (s, "r4") == 0 ||
892 strcmp (s, "r5") == 0 ||
893 strcmp (s, "r6") == 0 ||
894 strcmp (s, "r7") == 0)
895 emitcode ("mov", "%s,%s",
896 aop->aopu.aop_reg[offset]->dname, s);
898 emitcode ("mov", "%s,%s",
899 aop->aopu.aop_reg[offset]->name, s);
906 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff)
914 emitcode ("inc", "dptr");
917 while (offset < aop->coff)
920 emitcode ("lcall", "__decdptr");
925 /* if not in accumulater */
928 emitcode ("movx", "@dptr,a");
933 while (offset > aop->coff)
936 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
938 while (offset < aop->coff)
941 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
948 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
954 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
956 else if (strcmp (s, "r0") == 0 ||
957 strcmp (s, "r1") == 0 ||
958 strcmp (s, "r2") == 0 ||
959 strcmp (s, "r3") == 0 ||
960 strcmp (s, "r4") == 0 ||
961 strcmp (s, "r5") == 0 ||
962 strcmp (s, "r6") == 0 ||
963 strcmp (s, "r7") == 0)
966 sprintf (buffer, "a%s", s);
967 emitcode ("mov", "@%s,%s",
968 aop->aopu.aop_ptr->name, buffer);
971 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
976 if (strcmp (s, "a") == 0)
977 emitcode ("push", "acc");
979 emitcode ("push", "%s", s);
984 /* if bit variable */
985 if (!aop->aopu.aop_dir)
987 emitcode ("clr", "a");
988 emitcode ("rlc", "a");
993 emitcode ("clr", "%s", aop->aopu.aop_dir);
995 emitcode ("setb", "%s", aop->aopu.aop_dir);
996 else if (!strcmp (s, "c"))
997 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1000 if (strcmp (s, "a"))
1005 symbol *lbl = newiTempLabel (NULL);
1006 emitcode ("clr", "c");
1007 emitcode ("jz", "%05d$", lbl->key + 100);
1008 emitcode ("cpl", "c");
1009 emitcode ("", "%05d$:", lbl->key + 100);
1010 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1018 if (strcmp (aop->aopu.aop_str[offset], s))
1019 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1024 if (!offset && (strcmp (s, "acc") == 0))
1027 if (strcmp (aop->aopu.aop_str[offset], s))
1028 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1032 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1033 "aopPut got unsupported aop->type");
1041 /*-----------------------------------------------------------------*/
1042 /* pointToEnd :- points to the last byte of the operand */
1043 /*-----------------------------------------------------------------*/
1045 pointToEnd (asmop * aop)
1051 aop->coff = count = (aop->size - 1);
1057 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1061 emitcode ("inc", "dptr");
1068 /*-----------------------------------------------------------------*/
1069 /* reAdjustPreg - points a register back to where it should */
1070 /*-----------------------------------------------------------------*/
1072 reAdjustPreg (asmop * aop)
1074 if ((aop->coff==0) || aop->size <= 1)
1082 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 emitcode ("lcall", "__decdptr");
1094 #define AOP(op) op->aop
1095 #define AOP_TYPE(op) AOP(op)->type
1096 #define AOP_SIZE(op) AOP(op)->size
1097 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1098 AOP_TYPE(x) == AOP_R0))
1100 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1101 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1103 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1104 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1105 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1107 /*-----------------------------------------------------------------*/
1108 /* genNotFloat - generates not for float operations */
1109 /*-----------------------------------------------------------------*/
1111 genNotFloat (operand * op, operand * res)
1117 /* we will put 127 in the first byte of
1119 aopPut (AOP (res), "#127", 0);
1120 size = AOP_SIZE (op) - 1;
1123 l = aopGet (op->aop, offset++, FALSE, FALSE);
1128 emitcode ("orl", "a,%s",
1130 offset++, FALSE, FALSE));
1133 tlbl = newiTempLabel (NULL);
1134 aopPut (res->aop, one, 1);
1135 emitcode ("jz", "%05d$", (tlbl->key + 100));
1136 aopPut (res->aop, zero, 1);
1137 emitcode ("", "%05d$:", (tlbl->key + 100));
1139 size = res->aop->size - 2;
1141 /* put zeros in the rest */
1143 aopPut (res->aop, zero, offset++);
1146 /*-----------------------------------------------------------------*/
1147 /* opIsGptr: returns non-zero if the passed operand is */
1148 /* a generic pointer type. */
1149 /*-----------------------------------------------------------------*/
1151 opIsGptr (operand * op)
1153 sym_link *type = operandType (op);
1155 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1162 /*-----------------------------------------------------------------*/
1163 /* getDataSize - get the operand data size */
1164 /*-----------------------------------------------------------------*/
1166 getDataSize (operand * op)
1169 size = AOP_SIZE (op);
1170 if (size == GPTRSIZE)
1172 sym_link *type = operandType (op);
1173 if (IS_GENPTR (type))
1175 /* generic pointer; arithmetic operations
1176 * should ignore the high byte (pointer type).
1184 /*-----------------------------------------------------------------*/
1185 /* outAcc - output Acc */
1186 /*-----------------------------------------------------------------*/
1188 outAcc (operand * result)
1191 size = getDataSize (result);
1194 aopPut (AOP (result), "a", 0);
1197 /* unsigned or positive */
1200 aopPut (AOP (result), zero, offset++);
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C */
1207 /*-----------------------------------------------------------------*/
1209 outBitC (operand * result)
1211 /* if the result is bit */
1212 if (AOP_TYPE (result) == AOP_CRY)
1213 aopPut (AOP (result), "c", 0);
1216 emitcode ("clr", "a");
1217 emitcode ("rlc", "a");
1222 /*-----------------------------------------------------------------*/
1223 /* toBoolean - emit code for orl a,operator(sizeop) */
1224 /*-----------------------------------------------------------------*/
1226 toBoolean (operand * oper)
1228 int size = AOP_SIZE (oper) - 1;
1230 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1232 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1236 /*-----------------------------------------------------------------*/
1237 /* genNot - generate code for ! operation */
1238 /*-----------------------------------------------------------------*/
1243 sym_link *optype = operandType (IC_LEFT (ic));
1245 /* assign asmOps to operand & result */
1246 aopOp (IC_LEFT (ic), ic, FALSE);
1247 aopOp (IC_RESULT (ic), ic, TRUE);
1249 /* if in bit space then a special case */
1250 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1252 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1253 emitcode ("cpl", "c");
1254 outBitC (IC_RESULT (ic));
1258 /* if type float then do float */
1259 if (IS_FLOAT (optype))
1261 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1265 toBoolean (IC_LEFT (ic));
1267 tlbl = newiTempLabel (NULL);
1268 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1269 emitcode ("", "%05d$:", tlbl->key + 100);
1270 outBitC (IC_RESULT (ic));
1273 /* release the aops */
1274 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1279 /*-----------------------------------------------------------------*/
1280 /* genCpl - generate code for complement */
1281 /*-----------------------------------------------------------------*/
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if both are in bit space then
1295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1296 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1299 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1300 emitcode ("cpl", "c");
1301 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1305 size = AOP_SIZE (IC_RESULT (ic));
1308 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1310 emitcode ("cpl", "a");
1311 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1316 /* release the aops */
1317 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1321 /*-----------------------------------------------------------------*/
1322 /* genUminusFloat - unary minus for floating points */
1323 /*-----------------------------------------------------------------*/
1325 genUminusFloat (operand * op, operand * result)
1327 int size, offset = 0;
1329 /* for this we just need to flip the
1330 first it then copy the rest in place */
1331 size = AOP_SIZE (op) - 1;
1332 l = aopGet (AOP (op), 3, FALSE, FALSE);
1336 emitcode ("cpl", "acc.7");
1337 aopPut (AOP (result), "a", 3);
1341 aopPut (AOP (result),
1342 aopGet (AOP (op), offset, FALSE, FALSE),
1348 /*-----------------------------------------------------------------*/
1349 /* genUminus - unary minus code generation */
1350 /*-----------------------------------------------------------------*/
1352 genUminus (iCode * ic)
1355 sym_link *optype, *rtype;
1359 aopOp (IC_LEFT (ic), ic, FALSE);
1360 aopOp (IC_RESULT (ic), ic, TRUE);
1362 /* if both in bit space then special
1364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1365 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1368 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1369 emitcode ("cpl", "c");
1370 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1374 optype = operandType (IC_LEFT (ic));
1375 rtype = operandType (IC_RESULT (ic));
1377 /* if float then do float stuff */
1378 if (IS_FLOAT (optype))
1380 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1384 /* otherwise subtract from zero */
1385 size = AOP_SIZE (IC_LEFT (ic));
1390 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1391 if (!strcmp (l, "a"))
1395 emitcode ("cpl", "a");
1396 emitcode ("addc", "a,#0");
1402 emitcode ("clr", "a");
1403 emitcode ("subb", "a,%s", l);
1405 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1408 /* if any remaining bytes in the result */
1409 /* we just need to propagate the sign */
1410 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1412 emitcode ("rlc", "a");
1413 emitcode ("subb", "a,acc");
1415 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* saveRegisters - will look for a call and save the registers */
1426 /*-----------------------------------------------------------------*/
1428 saveRegisters (iCode * lic)
1436 for (ic = lic; ic; ic = ic->next)
1437 if (ic->op == CALL || ic->op == PCALL)
1442 fprintf (stderr, "found parameter push with no function call\n");
1446 /* if the registers have been saved already or don't need to be then
1448 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1449 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
1452 /* find the registers in use at this time
1453 and push them away to safety */
1454 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1458 if (options.useXstack)
1460 if (bitVectBitValue (rsave, R0_IDX))
1461 emitcode ("mov", "b,r0");
1462 emitcode ("mov", "r0,%s", spname);
1463 for (i = 0; i < mcs51_nRegs; i++)
1465 if (bitVectBitValue (rsave, i))
1468 emitcode ("mov", "a,b");
1470 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1471 emitcode ("movx", "@r0,a");
1472 emitcode ("inc", "r0");
1475 emitcode ("mov", "%s,r0", spname);
1476 if (bitVectBitValue (rsave, R0_IDX))
1477 emitcode ("mov", "r0,b");
1480 for (i = 0; i < mcs51_nRegs; i++)
1482 if (bitVectBitValue (rsave, i))
1483 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1486 detype = getSpec (operandType (IC_LEFT (ic)));
1489 /*-----------------------------------------------------------------*/
1490 /* unsaveRegisters - pop the pushed registers */
1491 /*-----------------------------------------------------------------*/
1493 unsaveRegisters (iCode * ic)
1497 /* find the registers in use at this time
1498 and push them away to safety */
1499 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1502 if (options.useXstack)
1504 emitcode ("mov", "r0,%s", spname);
1505 for (i = mcs51_nRegs; i >= 0; i--)
1507 if (bitVectBitValue (rsave, i))
1509 emitcode ("dec", "r0");
1510 emitcode ("movx", "a,@r0");
1512 emitcode ("mov", "b,a");
1514 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1518 emitcode ("mov", "%s,r0", spname);
1519 if (bitVectBitValue (rsave, R0_IDX))
1520 emitcode ("mov", "r0,b");
1523 for (i = mcs51_nRegs; i >= 0; i--)
1525 if (bitVectBitValue (rsave, i))
1526 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1532 /*-----------------------------------------------------------------*/
1534 /*-----------------------------------------------------------------*/
1536 pushSide (operand * oper, int size)
1541 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1542 if (AOP_TYPE (oper) != AOP_REG &&
1543 AOP_TYPE (oper) != AOP_DIR &&
1546 emitcode ("mov", "a,%s", l);
1547 emitcode ("push", "acc");
1550 emitcode ("push", "%s", l);
1554 /*-----------------------------------------------------------------*/
1555 /* assignResultValue - */
1556 /*-----------------------------------------------------------------*/
1558 assignResultValue (operand * oper)
1561 int size = AOP_SIZE (oper);
1564 aopPut (AOP (oper), fReturn[offset], offset);
1570 /*-----------------------------------------------------------------*/
1571 /* genXpush - pushes onto the external stack */
1572 /*-----------------------------------------------------------------*/
1574 genXpush (iCode * ic)
1576 asmop *aop = newAsmop (0);
1578 int size, offset = 0;
1580 aopOp (IC_LEFT (ic), ic, FALSE);
1581 r = getFreePtr (ic, &aop, FALSE);
1584 emitcode ("mov", "%s,_spx", r->name);
1586 size = AOP_SIZE (IC_LEFT (ic));
1590 char *l = aopGet (AOP (IC_LEFT (ic)),
1591 offset++, FALSE, FALSE);
1593 emitcode ("movx", "@%s,a", r->name);
1594 emitcode ("inc", "%s", r->name);
1599 emitcode ("mov", "_spx,%s", r->name);
1601 freeAsmop (NULL, aop, ic, TRUE);
1602 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1605 /*-----------------------------------------------------------------*/
1606 /* genIpush - genrate code for pushing this gets a little complex */
1607 /*-----------------------------------------------------------------*/
1609 genIpush (iCode * ic)
1611 int size, offset = 0;
1614 /* if this is not a parm push : ie. it is spill push
1615 and spill push is always done on the local stack */
1619 /* and the item is spilt then do nothing */
1620 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1623 aopOp (IC_LEFT (ic), ic, FALSE);
1624 size = AOP_SIZE (IC_LEFT (ic));
1625 /* push it on the stack */
1628 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1634 emitcode ("push", "%s", l);
1639 /* this is a paramter push: in this case we call
1640 the routine to find the call and save those
1641 registers that need to be saved */
1644 /* if use external stack then call the external
1645 stack pushing routine */
1646 if (options.useXstack)
1652 /* then do the push */
1653 aopOp (IC_LEFT (ic), ic, FALSE);
1656 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1657 size = AOP_SIZE (IC_LEFT (ic));
1661 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1662 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1663 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1666 emitcode ("mov", "a,%s", l);
1667 emitcode ("push", "acc");
1670 emitcode ("push", "%s", l);
1673 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1676 /*-----------------------------------------------------------------*/
1677 /* genIpop - recover the registers: can happen only for spilling */
1678 /*-----------------------------------------------------------------*/
1680 genIpop (iCode * ic)
1685 /* if the temp was not pushed then */
1686 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1689 aopOp (IC_LEFT (ic), ic, FALSE);
1690 size = AOP_SIZE (IC_LEFT (ic));
1691 offset = (size - 1);
1693 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1696 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1699 /*-----------------------------------------------------------------*/
1700 /* unsaveRBank - restores the resgister bank from stack */
1701 /*-----------------------------------------------------------------*/
1703 unsaveRBank (int bank, iCode * ic, bool popPsw)
1709 if (options.useXstack)
1713 /* Assume r0 is available for use. */
1714 r = mcs51_regWithIdx (R0_IDX);;
1719 r = getFreePtr (ic, &aop, FALSE);
1721 emitcode ("mov", "%s,_spx", r->name);
1726 if (options.useXstack)
1728 emitcode ("movx", "a,@%s", r->name);
1729 emitcode ("mov", "psw,a");
1730 emitcode ("dec", "%s", r->name);
1734 emitcode ("pop", "psw");
1738 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1740 if (options.useXstack)
1742 emitcode ("movx", "a,@%s", r->name);
1743 emitcode ("mov", "(%s+%d),a",
1744 regs8051[i].base, 8 * bank + regs8051[i].offset);
1745 emitcode ("dec", "%s", r->name);
1749 emitcode ("pop", "(%s+%d)",
1750 regs8051[i].base, 8 * bank + regs8051[i].offset);
1753 if (options.useXstack)
1755 emitcode ("mov", "_spx,%s", r->name);
1760 freeAsmop (NULL, aop, ic, TRUE);
1764 /*-----------------------------------------------------------------*/
1765 /* saveRBank - saves an entire register bank on the stack */
1766 /*-----------------------------------------------------------------*/
1768 saveRBank (int bank, iCode * ic, bool pushPsw)
1774 if (options.useXstack)
1778 /* Assume r0 is available for use. */
1779 r = mcs51_regWithIdx (R0_IDX);;
1784 r = getFreePtr (ic, &aop, FALSE);
1786 emitcode ("mov", "%s,_spx", r->name);
1789 for (i = 0; i < mcs51_nRegs; i++)
1791 if (options.useXstack)
1793 emitcode ("inc", "%s", r->name);
1794 emitcode ("mov", "a,(%s+%d)",
1795 regs8051[i].base, 8 * bank + regs8051[i].offset);
1796 emitcode ("movx", "@%s,a", r->name);
1799 emitcode ("push", "(%s+%d)",
1800 regs8051[i].base, 8 * bank + regs8051[i].offset);
1805 if (options.useXstack)
1807 emitcode ("mov", "a,psw");
1808 emitcode ("movx", "@%s,a", r->name);
1809 emitcode ("inc", "%s", r->name);
1810 emitcode ("mov", "_spx,%s", r->name);
1815 emitcode ("push", "psw");
1818 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1823 freeAsmop (NULL, aop, ic, TRUE);
1832 /*-----------------------------------------------------------------*/
1833 /* genCall - generates a call statement */
1834 /*-----------------------------------------------------------------*/
1836 genCall (iCode * ic)
1839 bool restoreBank = FALSE;
1840 bool swapBanks = FALSE;
1842 /* if send set is not empty the assign */
1847 for (sic = setFirstItem (_G.sendSet); sic;
1848 sic = setNextItem (_G.sendSet))
1850 int size, offset = 0;
1851 aopOp (IC_LEFT (sic), sic, FALSE);
1852 size = AOP_SIZE (IC_LEFT (sic));
1855 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1857 if (strcmp (l, fReturn[offset]))
1858 emitcode ("mov", "%s,%s",
1863 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1868 /* if we are calling a not _naked function that is not using
1869 the same register bank then we need to save the
1870 destination registers on the stack */
1871 detype = getSpec (operandType (IC_LEFT (ic)));
1872 if (detype && !SPEC_NAKED(detype) &&
1873 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1874 IS_ISR (currFunc->etype))
1878 /* This is unexpected; the bank should have been saved in
1881 saveRBank (SPEC_BANK (detype), ic, FALSE);
1887 /* if caller saves & we have not saved then */
1893 emitcode ("mov", "psw,#0x%02x",
1894 ((SPEC_BANK(detype)) << 3) & 0xff);
1898 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1899 OP_SYMBOL (IC_LEFT (ic))->rname :
1900 OP_SYMBOL (IC_LEFT (ic))->name));
1904 emitcode ("mov", "psw,#0x%02x",
1905 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
1908 /* if we need assign a result value */
1909 if ((IS_ITEMP (IC_RESULT (ic)) &&
1910 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1911 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1912 IS_TRUE_SYMOP (IC_RESULT (ic)))
1916 aopOp (IC_RESULT (ic), ic, FALSE);
1919 assignResultValue (IC_RESULT (ic));
1921 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1924 /* adjust the stack for parameters if
1929 if (ic->parmBytes > 3)
1931 emitcode ("mov", "a,%s", spname);
1932 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1933 emitcode ("mov", "%s,a", spname);
1936 for (i = 0; i < ic->parmBytes; i++)
1937 emitcode ("dec", "%s", spname);
1940 /* if we hade saved some registers then unsave them */
1941 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1942 unsaveRegisters (ic);
1944 /* if register bank was saved then pop them */
1946 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
1949 /*-----------------------------------------------------------------*/
1950 /* genPcall - generates a call by pointer statement */
1951 /*-----------------------------------------------------------------*/
1953 genPcall (iCode * ic)
1956 symbol *rlbl = newiTempLabel (NULL);
1959 /* if caller saves & we have not saved then */
1963 /* if we are calling a function that is not using
1964 the same register bank then we need to save the
1965 destination registers on the stack */
1966 detype = getSpec (operandType (IC_LEFT (ic)));
1968 IS_ISR (currFunc->etype) &&
1969 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1970 saveRBank (SPEC_BANK (detype), ic, TRUE);
1973 /* push the return address on to the stack */
1974 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1975 emitcode ("push", "acc");
1976 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1977 emitcode ("push", "acc");
1979 /* now push the calling address */
1980 aopOp (IC_LEFT (ic), ic, FALSE);
1982 pushSide (IC_LEFT (ic), FPTRSIZE);
1984 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1986 /* if send set is not empty the assign */
1991 for (sic = setFirstItem (_G.sendSet); sic;
1992 sic = setNextItem (_G.sendSet))
1994 int size, offset = 0;
1995 aopOp (IC_LEFT (sic), sic, FALSE);
1996 size = AOP_SIZE (IC_LEFT (sic));
1999 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2001 if (strcmp (l, fReturn[offset]))
2002 emitcode ("mov", "%s,%s",
2007 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2012 emitcode ("ret", "");
2013 emitcode ("", "%05d$:", (rlbl->key + 100));
2016 /* if we need assign a result value */
2017 if ((IS_ITEMP (IC_RESULT (ic)) &&
2018 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2019 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2020 IS_TRUE_SYMOP (IC_RESULT (ic)))
2024 aopOp (IC_RESULT (ic), ic, FALSE);
2027 assignResultValue (IC_RESULT (ic));
2029 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2032 /* adjust the stack for parameters if
2037 if (ic->parmBytes > 3)
2039 emitcode ("mov", "a,%s", spname);
2040 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2041 emitcode ("mov", "%s,a", spname);
2044 for (i = 0; i < ic->parmBytes; i++)
2045 emitcode ("dec", "%s", spname);
2049 /* if register bank was saved then unsave them */
2051 (SPEC_BANK (currFunc->etype) !=
2052 SPEC_BANK (detype)))
2053 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2055 /* if we hade saved some registers then
2058 unsaveRegisters (ic);
2062 /*-----------------------------------------------------------------*/
2063 /* resultRemat - result is rematerializable */
2064 /*-----------------------------------------------------------------*/
2066 resultRemat (iCode * ic)
2068 if (SKIP_IC (ic) || ic->op == IFX)
2071 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2073 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2074 if (sym->remat && !POINTER_SET (ic))
2081 #if defined(__BORLANDC__) || defined(_MSC_VER)
2082 #define STRCASECMP stricmp
2084 #define STRCASECMP strcasecmp
2087 /*-----------------------------------------------------------------*/
2088 /* inExcludeList - return 1 if the string is in exclude Reg list */
2089 /*-----------------------------------------------------------------*/
2091 inExcludeList (char *s)
2095 if (options.excludeRegs[i] &&
2096 STRCASECMP (options.excludeRegs[i], "none") == 0)
2099 for (i = 0; options.excludeRegs[i]; i++)
2101 if (options.excludeRegs[i] &&
2102 STRCASECMP (s, options.excludeRegs[i]) == 0)
2108 /*-----------------------------------------------------------------*/
2109 /* genFunction - generated code for function entry */
2110 /*-----------------------------------------------------------------*/
2112 genFunction (iCode * ic)
2116 bool switchedPSW = FALSE;
2119 /* create the function header */
2120 emitcode (";", "-----------------------------------------");
2121 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2122 emitcode (";", "-----------------------------------------");
2124 emitcode ("", "%s:", sym->rname);
2125 fetype = getSpec (operandType (IC_LEFT (ic)));
2127 if (SPEC_NAKED(fetype))
2129 emitcode(";", "naked function: no prologue.");
2133 /* if critical function then turn interrupts off */
2134 if (SPEC_CRTCL (fetype))
2135 emitcode ("clr", "ea");
2137 /* here we need to generate the equates for the
2138 register bank if required */
2139 if (SPEC_BANK (fetype) != rbank)
2143 rbank = SPEC_BANK (fetype);
2144 for (i = 0; i < mcs51_nRegs; i++)
2146 if (strcmp (regs8051[i].base, "0") == 0)
2147 emitcode ("", "%s = 0x%02x",
2149 8 * rbank + regs8051[i].offset);
2151 emitcode ("", "%s = %s + 0x%02x",
2154 8 * rbank + regs8051[i].offset);
2158 /* if this is an interrupt service routine then
2159 save acc, b, dpl, dph */
2160 if (IS_ISR (sym->etype))
2163 if (!inExcludeList ("acc"))
2164 emitcode ("push", "acc");
2165 if (!inExcludeList ("b"))
2166 emitcode ("push", "b");
2167 if (!inExcludeList ("dpl"))
2168 emitcode ("push", "dpl");
2169 if (!inExcludeList ("dph"))
2170 emitcode ("push", "dph");
2171 /* if this isr has no bank i.e. is going to
2172 run with bank 0 , then we need to save more
2174 if (!SPEC_BANK (sym->etype))
2177 /* if this function does not call any other
2178 function then we can be economical and
2179 save only those registers that are used */
2184 /* if any registers used */
2187 /* save the registers used */
2188 for (i = 0; i < sym->regsUsed->size; i++)
2190 if (bitVectBitValue (sym->regsUsed, i) ||
2191 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2192 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2199 /* this function has a function call cannot
2200 determines register usage so we will have to push the
2202 saveRBank (0, ic, FALSE);
2207 /* This ISR uses a non-zero bank.
2209 * We assume that the bank is available for our
2212 * However, if this ISR calls a function which uses some
2213 * other bank, we must save that bank entirely.
2215 unsigned long banksToSave = 0;
2220 #define MAX_REGISTER_BANKS 4
2225 for (i = ic; i; i = i->next)
2227 if (i->op == ENDFUNCTION)
2229 /* we got to the end OK. */
2237 detype = getSpec(operandType (IC_LEFT(i)));
2239 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2241 /* Mark this bank for saving. */
2242 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2244 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2248 banksToSave |= (1 << SPEC_BANK(detype));
2251 /* And note that we don't need to do it in
2259 /* This is a mess; we have no idea what
2260 * register bank the called function might
2263 * The only thing I can think of to do is
2264 * throw a warning and hope.
2266 werror(W_FUNCPTR_IN_USING_ISR);
2270 if (banksToSave && options.useXstack)
2272 /* Since we aren't passing it an ic,
2273 * saveRBank will assume r0 is available to abuse.
2275 * So switch to our (trashable) bank now, so
2276 * the caller's R0 isn't trashed.
2278 emitcode ("push", "psw");
2279 emitcode ("mov", "psw,#0x%02x",
2280 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2284 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2286 if (banksToSave & (1 << ix))
2288 saveRBank(ix, NULL, FALSE);
2292 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2297 /* if callee-save to be used for this function
2298 then save the registers being used in this function */
2299 if (sym->calleeSave)
2303 /* if any registers used */
2306 /* save the registers used */
2307 for (i = 0; i < sym->regsUsed->size; i++)
2309 if (bitVectBitValue (sym->regsUsed, i) ||
2310 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2312 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2320 /* set the register bank to the desired value */
2321 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2324 emitcode ("push", "psw");
2325 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2328 if (IS_RENT (sym->etype) || options.stackAuto)
2331 if (options.useXstack)
2333 emitcode ("mov", "r0,%s", spname);
2334 emitcode ("mov", "a,_bp");
2335 emitcode ("movx", "@r0,a");
2336 emitcode ("inc", "%s", spname);
2340 /* set up the stack */
2341 emitcode ("push", "_bp"); /* save the callers stack */
2343 emitcode ("mov", "_bp,%s", spname);
2346 /* adjust the stack for the function */
2352 werror (W_STACK_OVERFLOW, sym->name);
2354 if (i > 3 && sym->recvSize < 4)
2357 emitcode ("mov", "a,sp");
2358 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2359 emitcode ("mov", "sp,a");
2364 emitcode ("inc", "sp");
2370 emitcode ("mov", "a,_spx");
2371 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2372 emitcode ("mov", "_spx,a");
2377 /*-----------------------------------------------------------------*/
2378 /* genEndFunction - generates epilogue for functions */
2379 /*-----------------------------------------------------------------*/
2381 genEndFunction (iCode * ic)
2383 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2385 if (SPEC_NAKED(sym->etype))
2387 emitcode(";", "naked function: no epilogue.");
2391 if (IS_RENT (sym->etype) || options.stackAuto)
2393 emitcode ("mov", "%s,_bp", spname);
2396 /* if use external stack but some variables were
2397 added to the local stack then decrement the
2399 if (options.useXstack && sym->stack)
2401 emitcode ("mov", "a,sp");
2402 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2403 emitcode ("mov", "sp,a");
2407 if ((IS_RENT (sym->etype) || options.stackAuto))
2409 if (options.useXstack)
2411 emitcode ("mov", "r0,%s", spname);
2412 emitcode ("movx", "a,@r0");
2413 emitcode ("mov", "_bp,a");
2414 emitcode ("dec", "%s", spname);
2418 emitcode ("pop", "_bp");
2422 /* restore the register bank */
2423 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2425 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2426 || !options.useXstack)
2428 /* Special case of ISR using non-zero bank with useXstack
2431 emitcode ("pop", "psw");
2435 if (IS_ISR (sym->etype))
2438 /* now we need to restore the registers */
2439 /* if this isr has no bank i.e. is going to
2440 run with bank 0 , then we need to save more
2442 if (!SPEC_BANK (sym->etype))
2444 /* if this function does not call any other
2445 function then we can be economical and
2446 save only those registers that are used */
2451 /* if any registers used */
2454 /* save the registers used */
2455 for (i = sym->regsUsed->size; i >= 0; i--)
2457 if (bitVectBitValue (sym->regsUsed, i) ||
2458 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2459 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2466 /* this function has a function call cannot
2467 determines register usage so we will have to pop the
2469 unsaveRBank (0, ic, FALSE);
2474 /* This ISR uses a non-zero bank.
2476 * Restore any register banks saved by genFunction
2479 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2482 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2484 if (savedBanks & (1 << ix))
2486 unsaveRBank(ix, NULL, FALSE);
2490 if (options.useXstack)
2492 /* Restore bank AFTER calling unsaveRBank,
2493 * since it can trash r0.
2495 emitcode ("pop", "psw");
2499 if (!inExcludeList ("dph"))
2500 emitcode ("pop", "dph");
2501 if (!inExcludeList ("dpl"))
2502 emitcode ("pop", "dpl");
2503 if (!inExcludeList ("b"))
2504 emitcode ("pop", "b");
2505 if (!inExcludeList ("acc"))
2506 emitcode ("pop", "acc");
2508 if (SPEC_CRTCL (sym->etype))
2509 emitcode ("setb", "ea");
2511 /* if debug then send end of function */
2512 /* if (options.debug && currFunc) */
2513 if (options.debug && currFunc)
2516 emitcode ("", "C$%s$%d$%d$%d ==.",
2517 FileBaseName (ic->filename), currFunc->lastLine,
2518 ic->level, ic->block);
2519 if (IS_STATIC (currFunc->etype))
2520 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2522 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2526 emitcode ("reti", "");
2530 if (SPEC_CRTCL (sym->etype))
2531 emitcode ("setb", "ea");
2533 if (sym->calleeSave)
2537 /* if any registers used */
2540 /* save the registers used */
2541 for (i = sym->regsUsed->size; i >= 0; i--)
2543 if (bitVectBitValue (sym->regsUsed, i) ||
2544 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2545 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2551 /* if debug then send end of function */
2552 if (options.debug && currFunc)
2555 emitcode ("", "C$%s$%d$%d$%d ==.",
2556 FileBaseName (ic->filename), currFunc->lastLine,
2557 ic->level, ic->block);
2558 if (IS_STATIC (currFunc->etype))
2559 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2561 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2565 emitcode ("ret", "");
2570 /*-----------------------------------------------------------------*/
2571 /* genRet - generate code for return statement */
2572 /*-----------------------------------------------------------------*/
2576 int size, offset = 0, pushed = 0;
2578 /* if we have no return value then
2579 just generate the "ret" */
2583 /* we have something to return then
2584 move the return value into place */
2585 aopOp (IC_LEFT (ic), ic, FALSE);
2586 size = AOP_SIZE (IC_LEFT (ic));
2591 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2594 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2596 emitcode ("push", "%s", l);
2601 l = aopGet (AOP (IC_LEFT (ic)), offset,
2603 if (strcmp (fReturn[offset], l))
2604 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2613 if (strcmp (fReturn[pushed], "a"))
2614 emitcode ("pop", fReturn[pushed]);
2616 emitcode ("pop", "acc");
2619 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2622 /* generate a jump to the return label
2623 if the next is not the return statement */
2624 if (!(ic->next && ic->next->op == LABEL &&
2625 IC_LABEL (ic->next) == returnLabel))
2627 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2631 /*-----------------------------------------------------------------*/
2632 /* genLabel - generates a label */
2633 /*-----------------------------------------------------------------*/
2635 genLabel (iCode * ic)
2637 /* special case never generate */
2638 if (IC_LABEL (ic) == entryLabel)
2641 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2644 /*-----------------------------------------------------------------*/
2645 /* genGoto - generates a ljmp */
2646 /*-----------------------------------------------------------------*/
2648 genGoto (iCode * ic)
2650 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2653 /*-----------------------------------------------------------------*/
2654 /* findLabelBackwards: walks back through the iCode chain looking */
2655 /* for the given label. Returns number of iCode instructions */
2656 /* between that label and given ic. */
2657 /* Returns zero if label not found. */
2658 /*-----------------------------------------------------------------*/
2660 findLabelBackwards (iCode * ic, int key)
2669 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2671 /* printf("findLabelBackwards = %d\n", count); */
2679 /*-----------------------------------------------------------------*/
2680 /* genPlusIncr :- does addition with increment if possible */
2681 /*-----------------------------------------------------------------*/
2683 genPlusIncr (iCode * ic)
2685 unsigned int icount;
2686 unsigned int size = getDataSize (IC_RESULT (ic));
2688 /* will try to generate an increment */
2689 /* if the right side is not a literal
2691 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2694 /* if the literal value of the right hand side
2695 is greater than 4 then it is not worth it */
2696 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2699 /* if increment 16 bits in register */
2700 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2708 /* If the next instruction is a goto and the goto target
2709 * is < 10 instructions previous to this, we can generate
2710 * jumps straight to that target.
2712 if (ic->next && ic->next->op == GOTO
2713 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2714 && labelRange <= 10)
2716 emitcode (";", "tail increment optimized");
2717 tlbl = IC_LABEL (ic->next);
2722 tlbl = newiTempLabel (NULL);
2725 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2726 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2727 IS_AOP_PREG (IC_RESULT (ic)))
2728 emitcode ("cjne", "%s,#0x00,%05d$"
2729 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2733 emitcode ("clr", "a");
2734 emitcode ("cjne", "a,%s,%05d$"
2735 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2739 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2742 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2743 IS_AOP_PREG (IC_RESULT (ic)))
2744 emitcode ("cjne", "%s,#0x00,%05d$"
2745 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2748 emitcode ("cjne", "a,%s,%05d$"
2749 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2752 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2756 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2757 IS_AOP_PREG (IC_RESULT (ic)))
2758 emitcode ("cjne", "%s,#0x00,%05d$"
2759 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2763 emitcode ("cjne", "a,%s,%05d$"
2764 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2767 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2772 emitcode ("", "%05d$:", tlbl->key + 100);
2777 /* if the sizes are greater than 1 then we cannot */
2778 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2779 AOP_SIZE (IC_LEFT (ic)) > 1)
2782 /* we can if the aops of the left & result match or
2783 if they are in registers and the registers are the
2785 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2790 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2791 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2792 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2798 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2807 /*-----------------------------------------------------------------*/
2808 /* outBitAcc - output a bit in acc */
2809 /*-----------------------------------------------------------------*/
2811 outBitAcc (operand * result)
2813 symbol *tlbl = newiTempLabel (NULL);
2814 /* if the result is a bit */
2815 if (AOP_TYPE (result) == AOP_CRY)
2817 aopPut (AOP (result), "a", 0);
2821 emitcode ("jz", "%05d$", tlbl->key + 100);
2822 emitcode ("mov", "a,%s", one);
2823 emitcode ("", "%05d$:", tlbl->key + 100);
2828 /*-----------------------------------------------------------------*/
2829 /* genPlusBits - generates code for addition of two bits */
2830 /*-----------------------------------------------------------------*/
2832 genPlusBits (iCode * ic)
2834 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2836 symbol *lbl = newiTempLabel (NULL);
2837 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2838 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2839 emitcode ("cpl", "c");
2840 emitcode ("", "%05d$:", (lbl->key + 100));
2841 outBitC (IC_RESULT (ic));
2845 emitcode ("clr", "a");
2846 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2847 emitcode ("rlc", "a");
2848 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2849 emitcode ("addc", "a,#0x00");
2850 outAcc (IC_RESULT (ic));
2855 /* This is the original version of this code.
2857 * This is being kept around for reference,
2858 * because I am not entirely sure I got it right...
2861 adjustArithmeticResult (iCode * ic)
2863 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2864 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2865 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2866 aopPut (AOP (IC_RESULT (ic)),
2867 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2870 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2871 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2872 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2873 aopPut (AOP (IC_RESULT (ic)),
2874 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2877 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2878 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2879 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2880 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2881 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2884 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2885 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2889 /* This is the pure and virtuous version of this code.
2890 * I'm pretty certain it's right, but not enough to toss the old
2894 adjustArithmeticResult (iCode * ic)
2896 if (opIsGptr (IC_RESULT (ic)) &&
2897 opIsGptr (IC_LEFT (ic)) &&
2898 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2900 aopPut (AOP (IC_RESULT (ic)),
2901 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2905 if (opIsGptr (IC_RESULT (ic)) &&
2906 opIsGptr (IC_RIGHT (ic)) &&
2907 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2909 aopPut (AOP (IC_RESULT (ic)),
2910 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2914 if (opIsGptr (IC_RESULT (ic)) &&
2915 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2916 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2917 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2918 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2921 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2922 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2927 /*-----------------------------------------------------------------*/
2928 /* genPlus - generates code for addition */
2929 /*-----------------------------------------------------------------*/
2931 genPlus (iCode * ic)
2933 int size, offset = 0;
2935 /* special cases :- */
2937 aopOp (IC_LEFT (ic), ic, FALSE);
2938 aopOp (IC_RIGHT (ic), ic, FALSE);
2939 aopOp (IC_RESULT (ic), ic, TRUE);
2941 /* if literal, literal on the right or
2942 if left requires ACC or right is already
2944 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2945 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2946 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2948 operand *t = IC_RIGHT (ic);
2949 IC_RIGHT (ic) = IC_LEFT (ic);
2953 /* if both left & right are in bit
2955 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2956 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2962 /* if left in bit space & right literal */
2963 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2964 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2966 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2967 /* if result in bit space */
2968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2970 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2971 emitcode ("cpl", "c");
2972 outBitC (IC_RESULT (ic));
2976 size = getDataSize (IC_RESULT (ic));
2979 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2980 emitcode ("addc", "a,#00");
2981 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2987 /* if I can do an increment instead
2988 of add then GOOD for ME */
2989 if (genPlusIncr (ic) == TRUE)
2992 size = getDataSize (IC_RESULT (ic));
2996 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2998 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3000 emitcode ("add", "a,%s",
3001 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3003 emitcode ("addc", "a,%s",
3004 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3008 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3010 emitcode ("add", "a,%s",
3011 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3013 emitcode ("addc", "a,%s",
3014 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3016 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3019 adjustArithmeticResult (ic);
3022 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3023 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3024 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3027 /*-----------------------------------------------------------------*/
3028 /* genMinusDec :- does subtraction with deccrement if possible */
3029 /*-----------------------------------------------------------------*/
3031 genMinusDec (iCode * ic)
3033 unsigned int icount;
3034 unsigned int size = getDataSize (IC_RESULT (ic));
3036 /* will try to generate an increment */
3037 /* if the right side is not a literal
3039 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3042 /* if the literal value of the right hand side
3043 is greater than 4 then it is not worth it */
3044 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3047 /* if decrement 16 bits in register */
3048 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3056 /* If the next instruction is a goto and the goto target
3057 * is <= 10 instructions previous to this, we can generate
3058 * jumps straight to that target.
3060 if (ic->next && ic->next->op == GOTO
3061 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3062 && labelRange <= 10)
3064 emitcode (";", "tail decrement optimized");
3065 tlbl = IC_LABEL (ic->next);
3070 tlbl = newiTempLabel (NULL);
3074 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3075 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3076 IS_AOP_PREG (IC_RESULT (ic)))
3077 emitcode ("cjne", "%s,#0xff,%05d$"
3078 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3082 emitcode ("mov", "a,#0xff");
3083 emitcode ("cjne", "a,%s,%05d$"
3084 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3087 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3090 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3091 IS_AOP_PREG (IC_RESULT (ic)))
3092 emitcode ("cjne", "%s,#0xff,%05d$"
3093 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3097 emitcode ("cjne", "a,%s,%05d$"
3098 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3101 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3105 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3106 IS_AOP_PREG (IC_RESULT (ic)))
3107 emitcode ("cjne", "%s,#0xff,%05d$"
3108 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3112 emitcode ("cjne", "a,%s,%05d$"
3113 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3116 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3120 emitcode ("", "%05d$:", tlbl->key + 100);
3125 /* if the sizes are greater than 1 then we cannot */
3126 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3127 AOP_SIZE (IC_LEFT (ic)) > 1)
3130 /* we can if the aops of the left & result match or
3131 if they are in registers and the registers are the
3133 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3137 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3145 /*-----------------------------------------------------------------*/
3146 /* addSign - complete with sign */
3147 /*-----------------------------------------------------------------*/
3149 addSign (operand * result, int offset, int sign)
3151 int size = (getDataSize (result) - offset);
3156 emitcode ("rlc", "a");
3157 emitcode ("subb", "a,acc");
3159 aopPut (AOP (result), "a", offset++);
3163 aopPut (AOP (result), zero, offset++);
3167 /*-----------------------------------------------------------------*/
3168 /* genMinusBits - generates code for subtraction of two bits */
3169 /*-----------------------------------------------------------------*/
3171 genMinusBits (iCode * ic)
3173 symbol *lbl = newiTempLabel (NULL);
3174 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3176 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3177 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3178 emitcode ("cpl", "c");
3179 emitcode ("", "%05d$:", (lbl->key + 100));
3180 outBitC (IC_RESULT (ic));
3184 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3185 emitcode ("subb", "a,acc");
3186 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3187 emitcode ("inc", "a");
3188 emitcode ("", "%05d$:", (lbl->key + 100));
3189 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3190 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3194 /*-----------------------------------------------------------------*/
3195 /* genMinus - generates code for subtraction */
3196 /*-----------------------------------------------------------------*/
3198 genMinus (iCode * ic)
3200 int size, offset = 0;
3201 unsigned long lit = 0L;
3203 aopOp (IC_LEFT (ic), ic, FALSE);
3204 aopOp (IC_RIGHT (ic), ic, FALSE);
3205 aopOp (IC_RESULT (ic), ic, TRUE);
3207 /* special cases :- */
3208 /* if both left & right are in bit space */
3209 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3210 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3216 /* if I can do an decrement instead
3217 of subtract then GOOD for ME */
3218 if (genMinusDec (ic) == TRUE)
3221 size = getDataSize (IC_RESULT (ic));
3223 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3229 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3233 /* if literal, add a,#-lit, else normal subb */
3236 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3237 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3238 emitcode ("subb", "a,%s",
3239 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3242 /* first add without previous c */
3244 emitcode ("add", "a,#0x%02x",
3245 (unsigned int) (lit & 0x0FFL));
3247 emitcode ("addc", "a,#0x%02x",
3248 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3250 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3253 adjustArithmeticResult (ic);
3256 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3257 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3258 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3262 /*-----------------------------------------------------------------*/
3263 /* genMultbits :- multiplication of bits */
3264 /*-----------------------------------------------------------------*/
3266 genMultbits (operand * left,
3270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3271 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3276 /*-----------------------------------------------------------------*/
3277 /* genMultOneByte : 8*8=8/16 bit multiplication */
3278 /*-----------------------------------------------------------------*/
3280 genMultOneByte (operand * left,
3284 sym_link *opetype = operandType (result);
3286 int size=AOP_SIZE(result);
3288 if (size<1 || size>2) {
3289 // this should never happen
3290 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3291 AOP_SIZE(result), __FILE__, lineno);
3295 /* (if two literals: the value is computed before) */
3296 /* if one literal, literal on the right */
3297 if (AOP_TYPE (left) == AOP_LIT)
3302 //emitcode (";", "swapped left and right");
3305 if (SPEC_USIGN(opetype)
3306 // ignore the sign of left and right, what else can we do?
3307 || (SPEC_USIGN(operandType(left)) &&
3308 SPEC_USIGN(operandType(right)))) {
3309 // just an unsigned 8*8=8/16 multiply
3310 //emitcode (";","unsigned");
3311 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3312 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3313 emitcode ("mul", "ab");
3314 aopPut (AOP (result), "a", 0);
3316 aopPut (AOP (result), "b", 1);
3321 // we have to do a signed multiply
3323 //emitcode (";", "signed");
3324 emitcode ("clr", "F0"); // reset sign flag
3325 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3327 lbl=newiTempLabel(NULL);
3328 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3329 // left side is negative, 8-bit two's complement, this fails for -128
3330 emitcode ("setb", "F0"); // set sign flag
3331 emitcode ("cpl", "a");
3332 emitcode ("inc", "a");
3334 emitcode ("", "%05d$:", lbl->key+100);
3337 if (AOP_TYPE(right)==AOP_LIT) {
3338 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3339 /* AND literal negative */
3341 emitcode ("cpl", "F0"); // complement sign flag
3342 emitcode ("mov", "b,#0x%02x", -val);
3344 emitcode ("mov", "b,#0x%02x", val);
3347 lbl=newiTempLabel(NULL);
3348 emitcode ("mov", "b,a");
3349 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3350 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3351 // right side is negative, 8-bit two's complement
3352 emitcode ("cpl", "F0"); // complement sign flag
3353 emitcode ("cpl", "a");
3354 emitcode ("inc", "a");
3355 emitcode ("", "%05d$:", lbl->key+100);
3357 emitcode ("mul", "ab");
3359 lbl=newiTempLabel(NULL);
3360 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3361 // only ONE op was negative, we have to do a 8/16-bit two's complement
3362 emitcode ("cpl", "a"); // lsb
3364 emitcode ("inc", "a");
3366 emitcode ("add", "a,#1");
3367 emitcode ("xch", "a,b");
3368 emitcode ("cpl", "a"); // msb
3369 emitcode ("addc", "a,#0");
3370 emitcode ("xch", "a,b");
3373 emitcode ("", "%05d$:", lbl->key+100);
3374 aopPut (AOP (result), "a", 0);
3376 aopPut (AOP (result), "b", 1);
3380 /*-----------------------------------------------------------------*/
3381 /* genMult - generates code for multiplication */
3382 /*-----------------------------------------------------------------*/
3384 genMult (iCode * ic)
3386 operand *left = IC_LEFT (ic);
3387 operand *right = IC_RIGHT (ic);
3388 operand *result = IC_RESULT (ic);
3390 /* assign the amsops */
3391 aopOp (left, ic, FALSE);
3392 aopOp (right, ic, FALSE);
3393 aopOp (result, ic, TRUE);
3395 /* special cases first */
3397 if (AOP_TYPE (left) == AOP_CRY &&
3398 AOP_TYPE (right) == AOP_CRY)
3400 genMultbits (left, right, result);
3404 /* if both are of size == 1 */
3405 if (AOP_SIZE (left) == 1 &&
3406 AOP_SIZE (right) == 1)
3408 genMultOneByte (left, right, result);
3412 /* should have been converted to function call */
3416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3418 freeAsmop (result, NULL, ic, TRUE);
3421 /*-----------------------------------------------------------------*/
3422 /* genDivbits :- division of bits */
3423 /*-----------------------------------------------------------------*/
3425 genDivbits (operand * left,
3432 /* the result must be bit */
3433 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3434 l = aopGet (AOP (left), 0, FALSE, FALSE);
3438 emitcode ("div", "ab");
3439 emitcode ("rrc", "a");
3440 aopPut (AOP (result), "c", 0);
3443 /*-----------------------------------------------------------------*/
3444 /* genDivOneByte : 8 bit division */
3445 /*-----------------------------------------------------------------*/
3447 genDivOneByte (operand * left,
3451 sym_link *opetype = operandType (result);
3456 size = AOP_SIZE (result) - 1;
3458 /* signed or unsigned */
3459 if (SPEC_USIGN (opetype))
3461 /* unsigned is easy */
3462 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3463 l = aopGet (AOP (left), 0, FALSE, FALSE);
3465 emitcode ("div", "ab");
3466 aopPut (AOP (result), "a", 0);
3468 aopPut (AOP (result), zero, offset++);
3472 /* signed is a little bit more difficult */
3474 /* save the signs of the operands */
3475 l = aopGet (AOP (left), 0, FALSE, FALSE);
3477 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3478 emitcode ("push", "acc"); /* save it on the stack */
3480 /* now sign adjust for both left & right */
3481 l = aopGet (AOP (right), 0, FALSE, FALSE);
3483 lbl = newiTempLabel (NULL);
3484 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3485 emitcode ("cpl", "a");
3486 emitcode ("inc", "a");
3487 emitcode ("", "%05d$:", (lbl->key + 100));
3488 emitcode ("mov", "b,a");
3490 /* sign adjust left side */
3491 l = aopGet (AOP (left), 0, FALSE, FALSE);
3494 lbl = newiTempLabel (NULL);
3495 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3496 emitcode ("cpl", "a");
3497 emitcode ("inc", "a");
3498 emitcode ("", "%05d$:", (lbl->key + 100));
3500 /* now the division */
3501 emitcode ("div", "ab");
3502 /* we are interested in the lower order
3504 emitcode ("mov", "b,a");
3505 lbl = newiTempLabel (NULL);
3506 emitcode ("pop", "acc");
3507 /* if there was an over flow we don't
3508 adjust the sign of the result */
3509 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3510 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3512 emitcode ("clr", "a");
3513 emitcode ("subb", "a,b");
3514 emitcode ("mov", "b,a");
3515 emitcode ("", "%05d$:", (lbl->key + 100));
3517 /* now we are done */
3518 aopPut (AOP (result), "b", 0);
3521 emitcode ("mov", "c,b.7");
3522 emitcode ("subb", "a,acc");
3525 aopPut (AOP (result), "a", offset++);
3529 /*-----------------------------------------------------------------*/
3530 /* genDiv - generates code for division */
3531 /*-----------------------------------------------------------------*/
3535 operand *left = IC_LEFT (ic);
3536 operand *right = IC_RIGHT (ic);
3537 operand *result = IC_RESULT (ic);
3539 /* assign the amsops */
3540 aopOp (left, ic, FALSE);
3541 aopOp (right, ic, FALSE);
3542 aopOp (result, ic, TRUE);
3544 /* special cases first */
3546 if (AOP_TYPE (left) == AOP_CRY &&
3547 AOP_TYPE (right) == AOP_CRY)
3549 genDivbits (left, right, result);
3553 /* if both are of size == 1 */
3554 if (AOP_SIZE (left) == 1 &&
3555 AOP_SIZE (right) == 1)
3557 genDivOneByte (left, right, result);
3561 /* should have been converted to function call */
3564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3566 freeAsmop (result, NULL, ic, TRUE);
3569 /*-----------------------------------------------------------------*/
3570 /* genModbits :- modulus of bits */
3571 /*-----------------------------------------------------------------*/
3573 genModbits (operand * left,
3580 /* the result must be bit */
3581 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3582 l = aopGet (AOP (left), 0, FALSE, FALSE);
3586 emitcode ("div", "ab");
3587 emitcode ("mov", "a,b");
3588 emitcode ("rrc", "a");
3589 aopPut (AOP (result), "c", 0);
3592 /*-----------------------------------------------------------------*/
3593 /* genModOneByte : 8 bit modulus */
3594 /*-----------------------------------------------------------------*/
3596 genModOneByte (operand * left,
3600 sym_link *opetype = operandType (result);
3604 /* signed or unsigned */
3605 if (SPEC_USIGN (opetype))
3607 /* unsigned is easy */
3608 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3609 l = aopGet (AOP (left), 0, FALSE, FALSE);
3611 emitcode ("div", "ab");
3612 aopPut (AOP (result), "b", 0);
3616 /* signed is a little bit more difficult */
3618 /* save the signs of the operands */
3619 l = aopGet (AOP (left), 0, FALSE, FALSE);
3622 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3623 emitcode ("push", "acc"); /* save it on the stack */
3625 /* now sign adjust for both left & right */
3626 l = aopGet (AOP (right), 0, FALSE, FALSE);
3629 lbl = newiTempLabel (NULL);
3630 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3631 emitcode ("cpl", "a");
3632 emitcode ("inc", "a");
3633 emitcode ("", "%05d$:", (lbl->key + 100));
3634 emitcode ("mov", "b,a");
3636 /* sign adjust left side */
3637 l = aopGet (AOP (left), 0, FALSE, FALSE);
3640 lbl = newiTempLabel (NULL);
3641 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3642 emitcode ("cpl", "a");
3643 emitcode ("inc", "a");
3644 emitcode ("", "%05d$:", (lbl->key + 100));
3646 /* now the multiplication */
3647 emitcode ("div", "ab");
3648 /* we are interested in the lower order
3650 lbl = newiTempLabel (NULL);
3651 emitcode ("pop", "acc");
3652 /* if there was an over flow we don't
3653 adjust the sign of the result */
3654 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3655 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3657 emitcode ("clr", "a");
3658 emitcode ("subb", "a,b");
3659 emitcode ("mov", "b,a");
3660 emitcode ("", "%05d$:", (lbl->key + 100));
3662 /* now we are done */
3663 aopPut (AOP (result), "b", 0);
3667 /*-----------------------------------------------------------------*/
3668 /* genMod - generates code for division */
3669 /*-----------------------------------------------------------------*/
3673 operand *left = IC_LEFT (ic);
3674 operand *right = IC_RIGHT (ic);
3675 operand *result = IC_RESULT (ic);
3677 /* assign the amsops */
3678 aopOp (left, ic, FALSE);
3679 aopOp (right, ic, FALSE);
3680 aopOp (result, ic, TRUE);
3682 /* special cases first */
3684 if (AOP_TYPE (left) == AOP_CRY &&
3685 AOP_TYPE (right) == AOP_CRY)
3687 genModbits (left, right, result);
3691 /* if both are of size == 1 */
3692 if (AOP_SIZE (left) == 1 &&
3693 AOP_SIZE (right) == 1)
3695 genModOneByte (left, right, result);
3699 /* should have been converted to function call */
3703 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3705 freeAsmop (result, NULL, ic, TRUE);
3708 /*-----------------------------------------------------------------*/
3709 /* genIfxJump :- will create a jump depending on the ifx */
3710 /*-----------------------------------------------------------------*/
3712 genIfxJump (iCode * ic, char *jval)
3715 symbol *tlbl = newiTempLabel (NULL);
3718 /* if true label then we jump if condition
3722 jlbl = IC_TRUE (ic);
3723 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3724 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3728 /* false label is present */
3729 jlbl = IC_FALSE (ic);
3730 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3731 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3733 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3734 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3736 emitcode (inst, "%05d$", tlbl->key + 100);
3737 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3738 emitcode ("", "%05d$:", tlbl->key + 100);
3740 /* mark the icode as generated */
3744 /*-----------------------------------------------------------------*/
3745 /* genCmp :- greater or less than comparison */
3746 /*-----------------------------------------------------------------*/
3748 genCmp (operand * left, operand * right,
3749 operand * result, iCode * ifx, int sign, iCode *ic)
3751 int size, offset = 0;
3752 unsigned long lit = 0L;
3754 /* if left & right are bit variables */
3755 if (AOP_TYPE (left) == AOP_CRY &&
3756 AOP_TYPE (right) == AOP_CRY)
3758 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3759 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3763 /* subtract right from left if at the
3764 end the carry flag is set then we know that
3765 left is greater than right */
3766 size = max (AOP_SIZE (left), AOP_SIZE (right));
3768 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3769 if ((size == 1) && !sign &&
3770 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3772 symbol *lbl = newiTempLabel (NULL);
3773 emitcode ("cjne", "%s,%s,%05d$",
3774 aopGet (AOP (left), offset, FALSE, FALSE),
3775 aopGet (AOP (right), offset, FALSE, FALSE),
3777 emitcode ("", "%05d$:", lbl->key + 100);
3781 if (AOP_TYPE (right) == AOP_LIT)
3783 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3784 /* optimize if(x < 0) or if(x >= 0) */
3793 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3794 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3796 genIfxJump (ifx, "acc.7");
3800 emitcode ("rlc", "a");
3808 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3809 if (sign && size == 0)
3811 emitcode ("xrl", "a,#0x80");
3812 if (AOP_TYPE (right) == AOP_LIT)
3814 unsigned long lit = (unsigned long)
3815 floatFromVal (AOP (right)->aopu.aop_lit);
3816 emitcode ("subb", "a,#0x%02x",
3817 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3821 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3822 emitcode ("xrl", "b,#0x80");
3823 emitcode ("subb", "a,b");
3827 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3833 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3834 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3835 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3841 /* if the result is used in the next
3842 ifx conditional branch then generate
3843 code a little differently */
3845 genIfxJump (ifx, "c");
3848 /* leave the result in acc */
3852 /*-----------------------------------------------------------------*/
3853 /* genCmpGt :- greater than comparison */
3854 /*-----------------------------------------------------------------*/
3856 genCmpGt (iCode * ic, iCode * ifx)
3858 operand *left, *right, *result;
3859 sym_link *letype, *retype;
3862 left = IC_LEFT (ic);
3863 right = IC_RIGHT (ic);
3864 result = IC_RESULT (ic);
3866 letype = getSpec (operandType (left));
3867 retype = getSpec (operandType (right));
3868 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3869 /* assign the amsops */
3870 aopOp (left, ic, FALSE);
3871 aopOp (right, ic, FALSE);
3872 aopOp (result, ic, TRUE);
3874 genCmp (right, left, result, ifx, sign,ic);
3876 freeAsmop (result, NULL, ic, TRUE);
3879 /*-----------------------------------------------------------------*/
3880 /* genCmpLt - less than comparisons */
3881 /*-----------------------------------------------------------------*/
3883 genCmpLt (iCode * ic, iCode * ifx)
3885 operand *left, *right, *result;
3886 sym_link *letype, *retype;
3889 left = IC_LEFT (ic);
3890 right = IC_RIGHT (ic);
3891 result = IC_RESULT (ic);
3893 letype = getSpec (operandType (left));
3894 retype = getSpec (operandType (right));
3895 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3897 /* assign the amsops */
3898 aopOp (left, ic, FALSE);
3899 aopOp (right, ic, FALSE);
3900 aopOp (result, ic, TRUE);
3902 genCmp (left, right, result, ifx, sign,ic);
3904 freeAsmop (result, NULL, ic, TRUE);
3907 /*-----------------------------------------------------------------*/
3908 /* gencjneshort - compare and jump if not equal */
3909 /*-----------------------------------------------------------------*/
3911 gencjneshort (operand * left, operand * right, symbol * lbl)
3913 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3915 unsigned long lit = 0L;
3917 /* if the left side is a literal or
3918 if the right is in a pointer register and left
3920 if ((AOP_TYPE (left) == AOP_LIT) ||
3921 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3927 if (AOP_TYPE (right) == AOP_LIT)
3928 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3930 /* if the right side is a literal then anything goes */
3931 if (AOP_TYPE (right) == AOP_LIT &&
3932 AOP_TYPE (left) != AOP_DIR)
3936 emitcode ("cjne", "%s,%s,%05d$",
3937 aopGet (AOP (left), offset, FALSE, FALSE),
3938 aopGet (AOP (right), offset, FALSE, FALSE),
3944 /* if the right side is in a register or in direct space or
3945 if the left is a pointer register & right is not */
3946 else if (AOP_TYPE (right) == AOP_REG ||
3947 AOP_TYPE (right) == AOP_DIR ||
3948 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3949 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3953 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3954 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3955 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3956 emitcode ("jnz", "%05d$", lbl->key + 100);
3958 emitcode ("cjne", "a,%s,%05d$",
3959 aopGet (AOP (right), offset, FALSE, TRUE),
3966 /* right is a pointer reg need both a & b */
3969 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3970 if (strcmp (l, "b"))
3971 emitcode ("mov", "b,%s", l);
3972 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3973 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3979 /*-----------------------------------------------------------------*/
3980 /* gencjne - compare and jump if not equal */
3981 /*-----------------------------------------------------------------*/
3983 gencjne (operand * left, operand * right, symbol * lbl)
3985 symbol *tlbl = newiTempLabel (NULL);
3987 gencjneshort (left, right, lbl);
3989 emitcode ("mov", "a,%s", one);
3990 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3991 emitcode ("", "%05d$:", lbl->key + 100);
3992 emitcode ("clr", "a");
3993 emitcode ("", "%05d$:", tlbl->key + 100);
3996 /*-----------------------------------------------------------------*/
3997 /* genCmpEq - generates code for equal to */
3998 /*-----------------------------------------------------------------*/
4000 genCmpEq (iCode * ic, iCode * ifx)
4002 operand *left, *right, *result;
4004 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4005 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4006 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4008 /* if literal, literal on the right or
4009 if the right is in a pointer register and left
4011 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4012 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4014 operand *t = IC_RIGHT (ic);
4015 IC_RIGHT (ic) = IC_LEFT (ic);
4019 if (ifx && !AOP_SIZE (result))
4022 /* if they are both bit variables */
4023 if (AOP_TYPE (left) == AOP_CRY &&
4024 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4026 if (AOP_TYPE (right) == AOP_LIT)
4028 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4031 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4032 emitcode ("cpl", "c");
4036 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4040 emitcode ("clr", "c");
4042 /* AOP_TYPE(right) == AOP_CRY */
4046 symbol *lbl = newiTempLabel (NULL);
4047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4048 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4049 emitcode ("cpl", "c");
4050 emitcode ("", "%05d$:", (lbl->key + 100));
4052 /* if true label then we jump if condition
4054 tlbl = newiTempLabel (NULL);
4057 emitcode ("jnc", "%05d$", tlbl->key + 100);
4058 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4062 emitcode ("jc", "%05d$", tlbl->key + 100);
4063 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4065 emitcode ("", "%05d$:", tlbl->key + 100);
4069 tlbl = newiTempLabel (NULL);
4070 gencjneshort (left, right, tlbl);
4073 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4074 emitcode ("", "%05d$:", tlbl->key + 100);
4078 symbol *lbl = newiTempLabel (NULL);
4079 emitcode ("sjmp", "%05d$", lbl->key + 100);
4080 emitcode ("", "%05d$:", tlbl->key + 100);
4081 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4082 emitcode ("", "%05d$:", lbl->key + 100);
4085 /* mark the icode as generated */
4090 /* if they are both bit variables */
4091 if (AOP_TYPE (left) == AOP_CRY &&
4092 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4094 if (AOP_TYPE (right) == AOP_LIT)
4096 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4099 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4100 emitcode ("cpl", "c");
4104 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4108 emitcode ("clr", "c");
4110 /* AOP_TYPE(right) == AOP_CRY */
4114 symbol *lbl = newiTempLabel (NULL);
4115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4116 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4117 emitcode ("cpl", "c");
4118 emitcode ("", "%05d$:", (lbl->key + 100));
4121 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4128 genIfxJump (ifx, "c");
4131 /* if the result is used in an arithmetic operation
4132 then put the result in place */
4137 gencjne (left, right, newiTempLabel (NULL));
4138 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4140 aopPut (AOP (result), "a", 0);
4145 genIfxJump (ifx, "a");
4148 /* if the result is used in an arithmetic operation
4149 then put the result in place */
4150 if (AOP_TYPE (result) != AOP_CRY)
4152 /* leave the result in acc */
4156 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4158 freeAsmop (result, NULL, ic, TRUE);
4161 /*-----------------------------------------------------------------*/
4162 /* ifxForOp - returns the icode containing the ifx for operand */
4163 /*-----------------------------------------------------------------*/
4165 ifxForOp (operand * op, iCode * ic)
4167 /* if true symbol then needs to be assigned */
4168 if (IS_TRUE_SYMOP (op))
4171 /* if this has register type condition and
4172 the next instruction is ifx with the same operand
4173 and live to of the operand is upto the ifx only then */
4175 ic->next->op == IFX &&
4176 IC_COND (ic->next)->key == op->key &&
4177 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4183 /*-----------------------------------------------------------------*/
4184 /* hasInc - operand is incremented before any other use */
4185 /*-----------------------------------------------------------------*/
4187 hasInc (operand *op, iCode *ic)
4189 sym_link *type = operandType(op);
4190 sym_link *retype = getSpec (type);
4191 iCode *lic = ic->next;
4194 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4195 isize = getSize(type->next);
4197 /* if operand of the form op = op + <sizeof *op> */
4198 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4199 isOperandEqual(IC_RESULT(lic),op) &&
4200 isOperandLiteral(IC_RIGHT(lic)) &&
4201 operandLitValue(IC_RIGHT(lic)) == isize) {
4204 /* if the operand used or deffed */
4205 if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4213 /*-----------------------------------------------------------------*/
4214 /* genAndOp - for && operation */
4215 /*-----------------------------------------------------------------*/
4217 genAndOp (iCode * ic)
4219 operand *left, *right, *result;
4222 /* note here that && operations that are in an
4223 if statement are taken away by backPatchLabels
4224 only those used in arthmetic operations remain */
4225 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4226 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4227 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4229 /* if both are bit variables */
4230 if (AOP_TYPE (left) == AOP_CRY &&
4231 AOP_TYPE (right) == AOP_CRY)
4233 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4234 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4239 tlbl = newiTempLabel (NULL);
4241 emitcode ("jz", "%05d$", tlbl->key + 100);
4243 emitcode ("", "%05d$:", tlbl->key + 100);
4247 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4248 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4249 freeAsmop (result, NULL, ic, TRUE);
4253 /*-----------------------------------------------------------------*/
4254 /* genOrOp - for || operation */
4255 /*-----------------------------------------------------------------*/
4257 genOrOp (iCode * ic)
4259 operand *left, *right, *result;
4262 /* note here that || operations that are in an
4263 if statement are taken away by backPatchLabels
4264 only those used in arthmetic operations remain */
4265 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4266 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4267 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4269 /* if both are bit variables */
4270 if (AOP_TYPE (left) == AOP_CRY &&
4271 AOP_TYPE (right) == AOP_CRY)
4273 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4274 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4279 tlbl = newiTempLabel (NULL);
4281 emitcode ("jnz", "%05d$", tlbl->key + 100);
4283 emitcode ("", "%05d$:", tlbl->key + 100);
4287 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4289 freeAsmop (result, NULL, ic, TRUE);
4292 /*-----------------------------------------------------------------*/
4293 /* isLiteralBit - test if lit == 2^n */
4294 /*-----------------------------------------------------------------*/
4296 isLiteralBit (unsigned long lit)
4298 unsigned long pw[32] =
4299 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4300 0x100L, 0x200L, 0x400L, 0x800L,
4301 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4302 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4303 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4304 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4305 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4308 for (idx = 0; idx < 32; idx++)
4314 /*-----------------------------------------------------------------*/
4315 /* continueIfTrue - */
4316 /*-----------------------------------------------------------------*/
4318 continueIfTrue (iCode * ic)
4321 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4325 /*-----------------------------------------------------------------*/
4327 /*-----------------------------------------------------------------*/
4329 jumpIfTrue (iCode * ic)
4332 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4336 /*-----------------------------------------------------------------*/
4337 /* jmpTrueOrFalse - */
4338 /*-----------------------------------------------------------------*/
4340 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4342 // ugly but optimized by peephole
4345 symbol *nlbl = newiTempLabel (NULL);
4346 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4347 emitcode ("", "%05d$:", tlbl->key + 100);
4348 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4349 emitcode ("", "%05d$:", nlbl->key + 100);
4353 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4354 emitcode ("", "%05d$:", tlbl->key + 100);
4359 /*-----------------------------------------------------------------*/
4360 /* genAnd - code for and */
4361 /*-----------------------------------------------------------------*/
4363 genAnd (iCode * ic, iCode * ifx)
4365 operand *left, *right, *result;
4366 int size, offset = 0;
4367 unsigned long lit = 0L;
4371 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4372 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4373 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4376 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4378 AOP_TYPE (left), AOP_TYPE (right));
4379 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4381 AOP_SIZE (left), AOP_SIZE (right));
4384 /* if left is a literal & right is not then exchange them */
4385 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4386 AOP_NEEDSACC (left))
4388 operand *tmp = right;
4393 /* if result = right then exchange them */
4394 if (sameRegs (AOP (result), AOP (right)))
4396 operand *tmp = right;
4401 /* if right is bit then exchange them */
4402 if (AOP_TYPE (right) == AOP_CRY &&
4403 AOP_TYPE (left) != AOP_CRY)
4405 operand *tmp = right;
4409 if (AOP_TYPE (right) == AOP_LIT)
4410 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4412 size = AOP_SIZE (result);
4415 // result = bit & yy;
4416 if (AOP_TYPE (left) == AOP_CRY)
4418 // c = bit & literal;
4419 if (AOP_TYPE (right) == AOP_LIT)
4423 if (size && sameRegs (AOP (result), AOP (left)))
4426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4431 if (size && (AOP_TYPE (result) == AOP_CRY))
4433 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4436 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4441 emitcode ("clr", "c");
4446 if (AOP_TYPE (right) == AOP_CRY)
4449 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4450 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4455 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4457 emitcode ("rrc", "a");
4458 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4466 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4467 genIfxJump (ifx, "c");
4471 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4472 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4473 if ((AOP_TYPE (right) == AOP_LIT) &&
4474 (AOP_TYPE (result) == AOP_CRY) &&
4475 (AOP_TYPE (left) != AOP_CRY))
4477 int posbit = isLiteralBit (lit);
4482 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4485 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4491 sprintf (buffer, "acc.%d", posbit & 0x07);
4492 genIfxJump (ifx, buffer);
4499 symbol *tlbl = newiTempLabel (NULL);
4500 int sizel = AOP_SIZE (left);
4502 emitcode ("setb", "c");
4505 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4507 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4509 if ((posbit = isLiteralBit (bytelit)) != 0)
4510 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4513 if (bytelit != 0x0FFL)
4514 emitcode ("anl", "a,%s",
4515 aopGet (AOP (right), offset, FALSE, TRUE));
4516 emitcode ("jnz", "%05d$", tlbl->key + 100);
4521 // bit = left & literal
4524 emitcode ("clr", "c");
4525 emitcode ("", "%05d$:", tlbl->key + 100);
4527 // if(left & literal)
4531 jmpTrueOrFalse (ifx, tlbl);
4539 /* if left is same as result */
4540 if (sameRegs (AOP (result), AOP (left)))
4542 for (; size--; offset++)
4544 if (AOP_TYPE (right) == AOP_LIT)
4546 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4548 else if (bytelit == 0)
4549 aopPut (AOP (result), zero, offset);
4550 else if (IS_AOP_PREG (result))
4552 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4553 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4554 aopPut (AOP (result), "a", offset);
4557 emitcode ("anl", "%s,%s",
4558 aopGet (AOP (left), offset, FALSE, TRUE),
4559 aopGet (AOP (right), offset, FALSE, FALSE));
4563 if (AOP_TYPE (left) == AOP_ACC)
4564 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4567 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4568 if (IS_AOP_PREG (result))
4570 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4571 aopPut (AOP (result), "a", offset);
4575 emitcode ("anl", "%s,a",
4576 aopGet (AOP (left), offset, FALSE, TRUE));
4583 // left & result in different registers
4584 if (AOP_TYPE (result) == AOP_CRY)
4587 // if(size), result in bit
4588 // if(!size && ifx), conditional oper: if(left & right)
4589 symbol *tlbl = newiTempLabel (NULL);
4590 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4592 emitcode ("setb", "c");
4595 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4596 emitcode ("anl", "a,%s",
4597 aopGet (AOP (right), offset, FALSE, FALSE));
4599 if (AOP_TYPE(left)==AOP_ACC) {
4600 emitcode("mov", "b,a");
4601 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4602 emitcode("anl", "a,b");
4604 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4605 emitcode ("anl", "a,%s",
4606 aopGet (AOP (left), offset, FALSE, FALSE));
4609 emitcode ("jnz", "%05d$", tlbl->key + 100);
4615 emitcode ("", "%05d$:", tlbl->key + 100);
4619 jmpTrueOrFalse (ifx, tlbl);
4623 for (; (size--); offset++)
4626 // result = left & right
4627 if (AOP_TYPE (right) == AOP_LIT)
4629 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4631 aopPut (AOP (result),
4632 aopGet (AOP (left), offset, FALSE, FALSE),
4636 else if (bytelit == 0)
4638 aopPut (AOP (result), zero, offset);
4642 // faster than result <- left, anl result,right
4643 // and better if result is SFR
4644 if (AOP_TYPE (left) == AOP_ACC)
4645 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4648 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4649 emitcode ("anl", "a,%s",
4650 aopGet (AOP (left), offset, FALSE, FALSE));
4652 aopPut (AOP (result), "a", offset);
4658 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4659 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4660 freeAsmop (result, NULL, ic, TRUE);
4663 /*-----------------------------------------------------------------*/
4664 /* genOr - code for or */
4665 /*-----------------------------------------------------------------*/
4667 genOr (iCode * ic, iCode * ifx)
4669 operand *left, *right, *result;
4670 int size, offset = 0;
4671 unsigned long lit = 0L;
4673 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4674 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4675 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4678 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4680 AOP_TYPE (left), AOP_TYPE (right));
4681 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4683 AOP_SIZE (left), AOP_SIZE (right));
4686 /* if left is a literal & right is not then exchange them */
4687 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4688 AOP_NEEDSACC (left))
4690 operand *tmp = right;
4695 /* if result = right then exchange them */
4696 if (sameRegs (AOP (result), AOP (right)))
4698 operand *tmp = right;
4703 /* if right is bit then exchange them */
4704 if (AOP_TYPE (right) == AOP_CRY &&
4705 AOP_TYPE (left) != AOP_CRY)
4707 operand *tmp = right;
4711 if (AOP_TYPE (right) == AOP_LIT)
4712 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4714 size = AOP_SIZE (result);
4718 if (AOP_TYPE (left) == AOP_CRY)
4720 if (AOP_TYPE (right) == AOP_LIT)
4722 // c = bit & literal;
4725 // lit != 0 => result = 1
4726 if (AOP_TYPE (result) == AOP_CRY)
4729 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4731 continueIfTrue (ifx);
4734 emitcode ("setb", "c");
4738 // lit == 0 => result = left
4739 if (size && sameRegs (AOP (result), AOP (left)))
4741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4746 if (AOP_TYPE (right) == AOP_CRY)
4749 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4750 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4755 symbol *tlbl = newiTempLabel (NULL);
4756 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4757 emitcode ("setb", "c");
4758 emitcode ("jb", "%s,%05d$",
4759 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4761 emitcode ("jnz", "%05d$", tlbl->key + 100);
4762 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4764 jmpTrueOrFalse (ifx, tlbl);
4770 emitcode ("", "%05d$:", tlbl->key + 100);
4779 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4780 genIfxJump (ifx, "c");
4784 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4785 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4786 if ((AOP_TYPE (right) == AOP_LIT) &&
4787 (AOP_TYPE (result) == AOP_CRY) &&
4788 (AOP_TYPE (left) != AOP_CRY))
4794 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4796 continueIfTrue (ifx);
4801 // lit = 0, result = boolean(left)
4803 emitcode ("setb", "c");
4807 symbol *tlbl = newiTempLabel (NULL);
4808 emitcode ("jnz", "%05d$", tlbl->key + 100);
4810 emitcode ("", "%05d$:", tlbl->key + 100);
4814 genIfxJump (ifx, "a");
4822 /* if left is same as result */
4823 if (sameRegs (AOP (result), AOP (left)))
4825 for (; size--; offset++)
4827 if (AOP_TYPE (right) == AOP_LIT)
4829 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4831 else if (IS_AOP_PREG (left))
4833 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4834 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4835 aopPut (AOP (result), "a", offset);
4838 emitcode ("orl", "%s,%s",
4839 aopGet (AOP (left), offset, FALSE, TRUE),
4840 aopGet (AOP (right), offset, FALSE, FALSE));
4844 if (AOP_TYPE (left) == AOP_ACC)
4845 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4848 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4849 if (IS_AOP_PREG (left))
4851 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4852 aopPut (AOP (result), "a", offset);
4855 emitcode ("orl", "%s,a",
4856 aopGet (AOP (left), offset, FALSE, TRUE));
4863 // left & result in different registers
4864 if (AOP_TYPE (result) == AOP_CRY)
4867 // if(size), result in bit
4868 // if(!size && ifx), conditional oper: if(left | right)
4869 symbol *tlbl = newiTempLabel (NULL);
4870 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4872 emitcode ("setb", "c");
4875 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4876 emitcode ("orl", "a,%s",
4877 aopGet (AOP (right), offset, FALSE, FALSE));
4879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4880 emitcode ("orl", "a,%s",
4881 aopGet (AOP (left), offset, FALSE, FALSE));
4883 emitcode ("jnz", "%05d$", tlbl->key + 100);
4889 emitcode ("", "%05d$:", tlbl->key + 100);
4893 jmpTrueOrFalse (ifx, tlbl);
4896 for (; (size--); offset++)
4899 // result = left & right
4900 if (AOP_TYPE (right) == AOP_LIT)
4902 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4904 aopPut (AOP (result),
4905 aopGet (AOP (left), offset, FALSE, FALSE),
4910 // faster than result <- left, anl result,right
4911 // and better if result is SFR
4912 if (AOP_TYPE (left) == AOP_ACC)
4913 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4916 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4917 emitcode ("orl", "a,%s",
4918 aopGet (AOP (left), offset, FALSE, FALSE));
4920 aopPut (AOP (result), "a", offset);
4925 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4926 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 freeAsmop (result, NULL, ic, TRUE);
4930 /*-----------------------------------------------------------------*/
4931 /* genXor - code for xclusive or */
4932 /*-----------------------------------------------------------------*/
4934 genXor (iCode * ic, iCode * ifx)
4936 operand *left, *right, *result;
4937 int size, offset = 0;
4938 unsigned long lit = 0L;
4940 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4941 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4942 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4945 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4947 AOP_TYPE (left), AOP_TYPE (right));
4948 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4950 AOP_SIZE (left), AOP_SIZE (right));
4953 /* if left is a literal & right is not ||
4954 if left needs acc & right does not */
4955 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4956 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4958 operand *tmp = right;
4963 /* if result = right then exchange them */
4964 if (sameRegs (AOP (result), AOP (right)))
4966 operand *tmp = right;
4971 /* if right is bit then exchange them */
4972 if (AOP_TYPE (right) == AOP_CRY &&
4973 AOP_TYPE (left) != AOP_CRY)
4975 operand *tmp = right;
4979 if (AOP_TYPE (right) == AOP_LIT)
4980 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4982 size = AOP_SIZE (result);
4986 if (AOP_TYPE (left) == AOP_CRY)
4988 if (AOP_TYPE (right) == AOP_LIT)
4990 // c = bit & literal;
4993 // lit>>1 != 0 => result = 1
4994 if (AOP_TYPE (result) == AOP_CRY)
4997 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4999 continueIfTrue (ifx);
5002 emitcode ("setb", "c");
5009 // lit == 0, result = left
5010 if (size && sameRegs (AOP (result), AOP (left)))
5012 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5016 // lit == 1, result = not(left)
5017 if (size && sameRegs (AOP (result), AOP (left)))
5019 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5024 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5025 emitcode ("cpl", "c");
5034 symbol *tlbl = newiTempLabel (NULL);
5035 if (AOP_TYPE (right) == AOP_CRY)
5038 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5042 int sizer = AOP_SIZE (right);
5044 // if val>>1 != 0, result = 1
5045 emitcode ("setb", "c");
5048 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5050 // test the msb of the lsb
5051 emitcode ("anl", "a,#0xfe");
5052 emitcode ("jnz", "%05d$", tlbl->key + 100);
5056 emitcode ("rrc", "a");
5058 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5059 emitcode ("cpl", "c");
5060 emitcode ("", "%05d$:", (tlbl->key + 100));
5067 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5068 genIfxJump (ifx, "c");
5072 if (sameRegs (AOP (result), AOP (left)))
5074 /* if left is same as result */
5075 for (; size--; offset++)
5077 if (AOP_TYPE (right) == AOP_LIT)
5079 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5081 else if (IS_AOP_PREG (left))
5083 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5084 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5085 aopPut (AOP (result), "a", offset);
5088 emitcode ("xrl", "%s,%s",
5089 aopGet (AOP (left), offset, FALSE, TRUE),
5090 aopGet (AOP (right), offset, FALSE, FALSE));
5094 if (AOP_TYPE (left) == AOP_ACC)
5095 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5098 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5099 if (IS_AOP_PREG (left))
5101 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5102 aopPut (AOP (result), "a", offset);
5105 emitcode ("xrl", "%s,a",
5106 aopGet (AOP (left), offset, FALSE, TRUE));
5113 // left & result in different registers
5114 if (AOP_TYPE (result) == AOP_CRY)
5117 // if(size), result in bit
5118 // if(!size && ifx), conditional oper: if(left ^ right)
5119 symbol *tlbl = newiTempLabel (NULL);
5120 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5122 emitcode ("setb", "c");
5125 if ((AOP_TYPE (right) == AOP_LIT) &&
5126 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5128 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5132 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5133 emitcode ("xrl", "a,%s",
5134 aopGet (AOP (right), offset, FALSE, FALSE));
5136 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5137 emitcode ("xrl", "a,%s",
5138 aopGet (AOP (left), offset, FALSE, FALSE));
5141 emitcode ("jnz", "%05d$", tlbl->key + 100);
5147 emitcode ("", "%05d$:", tlbl->key + 100);
5151 jmpTrueOrFalse (ifx, tlbl);
5154 for (; (size--); offset++)
5157 // result = left & right
5158 if (AOP_TYPE (right) == AOP_LIT)
5160 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5162 aopPut (AOP (result),
5163 aopGet (AOP (left), offset, FALSE, FALSE),
5168 // faster than result <- left, anl result,right
5169 // and better if result is SFR
5170 if (AOP_TYPE (left) == AOP_ACC)
5171 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5174 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5175 emitcode ("xrl", "a,%s",
5176 aopGet (AOP (left), offset, FALSE, TRUE));
5178 aopPut (AOP (result), "a", offset);
5183 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5184 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5185 freeAsmop (result, NULL, ic, TRUE);
5188 /*-----------------------------------------------------------------*/
5189 /* genInline - write the inline code out */
5190 /*-----------------------------------------------------------------*/
5192 genInline (iCode * ic)
5194 char *buffer, *bp, *bp1;
5196 _G.inLine += (!options.asmpeep);
5198 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5199 strcpy (buffer, IC_INLINE (ic));
5201 /* emit each line as a code */
5226 /* emitcode("",buffer); */
5227 _G.inLine -= (!options.asmpeep);
5230 /*-----------------------------------------------------------------*/
5231 /* genRRC - rotate right with carry */
5232 /*-----------------------------------------------------------------*/
5236 operand *left, *result;
5237 int size, offset = 0;
5240 /* rotate right with carry */
5241 left = IC_LEFT (ic);
5242 result = IC_RESULT (ic);
5243 aopOp (left, ic, FALSE);
5244 aopOp (result, ic, FALSE);
5246 /* move it to the result */
5247 size = AOP_SIZE (result);
5252 l = aopGet (AOP (left), offset, FALSE, FALSE);
5254 emitcode ("rrc", "a");
5255 if (AOP_SIZE (result) > 1)
5256 aopPut (AOP (result), "a", offset--);
5258 /* now we need to put the carry into the
5259 highest order byte of the result */
5260 if (AOP_SIZE (result) > 1)
5262 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5265 emitcode ("mov", "acc.7,c");
5266 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5267 freeAsmop (left, NULL, ic, TRUE);
5268 freeAsmop (result, NULL, ic, TRUE);
5271 /*-----------------------------------------------------------------*/
5272 /* genRLC - generate code for rotate left with carry */
5273 /*-----------------------------------------------------------------*/
5277 operand *left, *result;
5278 int size, offset = 0;
5281 /* rotate right with carry */
5282 left = IC_LEFT (ic);
5283 result = IC_RESULT (ic);
5284 aopOp (left, ic, FALSE);
5285 aopOp (result, ic, FALSE);
5287 /* move it to the result */
5288 size = AOP_SIZE (result);
5292 l = aopGet (AOP (left), offset, FALSE, FALSE);
5294 emitcode ("add", "a,acc");
5295 if (AOP_SIZE (result) > 1)
5296 aopPut (AOP (result), "a", offset++);
5299 l = aopGet (AOP (left), offset, FALSE, FALSE);
5301 emitcode ("rlc", "a");
5302 if (AOP_SIZE (result) > 1)
5303 aopPut (AOP (result), "a", offset++);
5306 /* now we need to put the carry into the
5307 highest order byte of the result */
5308 if (AOP_SIZE (result) > 1)
5310 l = aopGet (AOP (result), 0, FALSE, FALSE);
5313 emitcode ("mov", "acc.0,c");
5314 aopPut (AOP (result), "a", 0);
5315 freeAsmop (left, NULL, ic, TRUE);
5316 freeAsmop (result, NULL, ic, TRUE);
5319 /*-----------------------------------------------------------------*/
5320 /* genGetHbit - generates code get highest order bit */
5321 /*-----------------------------------------------------------------*/
5323 genGetHbit (iCode * ic)
5325 operand *left, *result;
5326 left = IC_LEFT (ic);
5327 result = IC_RESULT (ic);
5328 aopOp (left, ic, FALSE);
5329 aopOp (result, ic, FALSE);
5331 /* get the highest order byte into a */
5332 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5333 if (AOP_TYPE (result) == AOP_CRY)
5335 emitcode ("rlc", "a");
5340 emitcode ("rl", "a");
5341 emitcode ("anl", "a,#0x01");
5346 freeAsmop (left, NULL, ic, TRUE);
5347 freeAsmop (result, NULL, ic, TRUE);
5350 /*-----------------------------------------------------------------*/
5351 /* AccRol - rotate left accumulator by known count */
5352 /*-----------------------------------------------------------------*/
5354 AccRol (int shCount)
5356 shCount &= 0x0007; // shCount : 0..7
5363 emitcode ("rl", "a");
5366 emitcode ("rl", "a");
5367 emitcode ("rl", "a");
5370 emitcode ("swap", "a");
5371 emitcode ("rr", "a");
5374 emitcode ("swap", "a");
5377 emitcode ("swap", "a");
5378 emitcode ("rl", "a");
5381 emitcode ("rr", "a");
5382 emitcode ("rr", "a");
5385 emitcode ("rr", "a");
5390 /*-----------------------------------------------------------------*/
5391 /* AccLsh - left shift accumulator by known count */
5392 /*-----------------------------------------------------------------*/
5394 AccLsh (int shCount)
5399 emitcode ("add", "a,acc");
5400 else if (shCount == 2)
5402 emitcode ("add", "a,acc");
5403 emitcode ("add", "a,acc");
5407 /* rotate left accumulator */
5409 /* and kill the lower order bits */
5410 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5415 /*-----------------------------------------------------------------*/
5416 /* AccRsh - right shift accumulator by known count */
5417 /*-----------------------------------------------------------------*/
5419 AccRsh (int shCount)
5426 emitcode ("rrc", "a");
5430 /* rotate right accumulator */
5431 AccRol (8 - shCount);
5432 /* and kill the higher order bits */
5433 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5438 /*-----------------------------------------------------------------*/
5439 /* AccSRsh - signed right shift accumulator by known count */
5440 /*-----------------------------------------------------------------*/
5442 AccSRsh (int shCount)
5449 emitcode ("mov", "c,acc.7");
5450 emitcode ("rrc", "a");
5452 else if (shCount == 2)
5454 emitcode ("mov", "c,acc.7");
5455 emitcode ("rrc", "a");
5456 emitcode ("mov", "c,acc.7");
5457 emitcode ("rrc", "a");
5461 tlbl = newiTempLabel (NULL);
5462 /* rotate right accumulator */
5463 AccRol (8 - shCount);
5464 /* and kill the higher order bits */
5465 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5466 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5467 emitcode ("orl", "a,#0x%02x",
5468 (unsigned char) ~SRMask[shCount]);
5469 emitcode ("", "%05d$:", tlbl->key + 100);
5474 /*-----------------------------------------------------------------*/
5475 /* shiftR1Left2Result - shift right one byte from left to result */
5476 /*-----------------------------------------------------------------*/
5478 shiftR1Left2Result (operand * left, int offl,
5479 operand * result, int offr,
5480 int shCount, int sign)
5482 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5483 /* shift right accumulator */
5488 aopPut (AOP (result), "a", offr);
5491 /*-----------------------------------------------------------------*/
5492 /* shiftL1Left2Result - shift left one byte from left to result */
5493 /*-----------------------------------------------------------------*/
5495 shiftL1Left2Result (operand * left, int offl,
5496 operand * result, int offr, int shCount)
5499 l = aopGet (AOP (left), offl, FALSE, FALSE);
5501 /* shift left accumulator */
5503 aopPut (AOP (result), "a", offr);
5506 /*-----------------------------------------------------------------*/
5507 /* movLeft2Result - move byte from left to result */
5508 /*-----------------------------------------------------------------*/
5510 movLeft2Result (operand * left, int offl,
5511 operand * result, int offr, int sign)
5514 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5516 l = aopGet (AOP (left), offl, FALSE, FALSE);
5518 if (*l == '@' && (IS_AOP_PREG (result)))
5520 emitcode ("mov", "a,%s", l);
5521 aopPut (AOP (result), "a", offr);
5526 aopPut (AOP (result), l, offr);
5529 /* MSB sign in acc.7 ! */
5530 if (getDataSize (left) == offl + 1)
5532 emitcode ("mov", "a,%s", l);
5533 aopPut (AOP (result), "a", offr);
5540 /*-----------------------------------------------------------------*/
5541 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5542 /*-----------------------------------------------------------------*/
5546 emitcode ("rrc", "a");
5547 emitcode ("xch", "a,%s", x);
5548 emitcode ("rrc", "a");
5549 emitcode ("xch", "a,%s", x);
5552 /*-----------------------------------------------------------------*/
5553 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5554 /*-----------------------------------------------------------------*/
5558 emitcode ("xch", "a,%s", x);
5559 emitcode ("rlc", "a");
5560 emitcode ("xch", "a,%s", x);
5561 emitcode ("rlc", "a");
5564 /*-----------------------------------------------------------------*/
5565 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5566 /*-----------------------------------------------------------------*/
5570 emitcode ("xch", "a,%s", x);
5571 emitcode ("add", "a,acc");
5572 emitcode ("xch", "a,%s", x);
5573 emitcode ("rlc", "a");
5576 /*-----------------------------------------------------------------*/
5577 /* AccAXLsh - left shift a:x by known count (0..7) */
5578 /*-----------------------------------------------------------------*/
5580 AccAXLsh (char *x, int shCount)
5595 case 5: // AAAAABBB:CCCCCDDD
5597 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5599 emitcode ("anl", "a,#0x%02x",
5600 SLMask[shCount]); // BBB00000:CCCCCDDD
5602 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5604 AccRol (shCount); // DDDCCCCC:BBB00000
5606 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5608 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5610 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5612 emitcode ("anl", "a,#0x%02x",
5613 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5615 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5617 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5620 case 6: // AAAAAABB:CCCCCCDD
5621 emitcode ("anl", "a,#0x%02x",
5622 SRMask[shCount]); // 000000BB:CCCCCCDD
5623 emitcode ("mov", "c,acc.0"); // c = B
5624 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5626 AccAXRrl1 (x); // BCCCCCCD:D000000B
5627 AccAXRrl1 (x); // BBCCCCCC:DD000000
5629 emitcode("rrc","a");
5630 emitcode("xch","a,%s", x);
5631 emitcode("rrc","a");
5632 emitcode("mov","c,acc.0"); //<< get correct bit
5633 emitcode("xch","a,%s", x);
5635 emitcode("rrc","a");
5636 emitcode("xch","a,%s", x);
5637 emitcode("rrc","a");
5638 emitcode("xch","a,%s", x);
5641 case 7: // a:x <<= 7
5643 emitcode ("anl", "a,#0x%02x",
5644 SRMask[shCount]); // 0000000B:CCCCCCCD
5646 emitcode ("mov", "c,acc.0"); // c = B
5648 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5650 AccAXRrl1 (x); // BCCCCCCC:D0000000
5658 /*-----------------------------------------------------------------*/
5659 /* AccAXRsh - right shift a:x known count (0..7) */
5660 /*-----------------------------------------------------------------*/
5662 AccAXRsh (char *x, int shCount)
5670 AccAXRrl1 (x); // 0->a:x
5675 AccAXRrl1 (x); // 0->a:x
5678 AccAXRrl1 (x); // 0->a:x
5683 case 5: // AAAAABBB:CCCCCDDD = a:x
5685 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5687 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5689 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5691 emitcode ("anl", "a,#0x%02x",
5692 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5694 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5696 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5698 emitcode ("anl", "a,#0x%02x",
5699 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5701 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5703 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5705 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5708 case 6: // AABBBBBB:CCDDDDDD
5710 emitcode ("mov", "c,acc.7");
5711 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5713 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5715 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5717 emitcode ("anl", "a,#0x%02x",
5718 SRMask[shCount]); // 000000AA:BBBBBBCC
5721 case 7: // ABBBBBBB:CDDDDDDD
5723 emitcode ("mov", "c,acc.7"); // c = A
5725 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5727 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5729 emitcode ("anl", "a,#0x%02x",
5730 SRMask[shCount]); // 0000000A:BBBBBBBC
5738 /*-----------------------------------------------------------------*/
5739 /* AccAXRshS - right shift signed a:x known count (0..7) */
5740 /*-----------------------------------------------------------------*/
5742 AccAXRshS (char *x, int shCount)
5750 emitcode ("mov", "c,acc.7");
5751 AccAXRrl1 (x); // s->a:x
5755 emitcode ("mov", "c,acc.7");
5756 AccAXRrl1 (x); // s->a:x
5758 emitcode ("mov", "c,acc.7");
5759 AccAXRrl1 (x); // s->a:x
5764 case 5: // AAAAABBB:CCCCCDDD = a:x
5766 tlbl = newiTempLabel (NULL);
5767 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5769 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5771 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5773 emitcode ("anl", "a,#0x%02x",
5774 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5776 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5778 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5780 emitcode ("anl", "a,#0x%02x",
5781 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5783 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5785 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5787 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5789 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5790 emitcode ("orl", "a,#0x%02x",
5791 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5793 emitcode ("", "%05d$:", tlbl->key + 100);
5794 break; // SSSSAAAA:BBBCCCCC
5796 case 6: // AABBBBBB:CCDDDDDD
5798 tlbl = newiTempLabel (NULL);
5799 emitcode ("mov", "c,acc.7");
5800 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5802 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5804 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5806 emitcode ("anl", "a,#0x%02x",
5807 SRMask[shCount]); // 000000AA:BBBBBBCC
5809 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5810 emitcode ("orl", "a,#0x%02x",
5811 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5813 emitcode ("", "%05d$:", tlbl->key + 100);
5815 case 7: // ABBBBBBB:CDDDDDDD
5817 tlbl = newiTempLabel (NULL);
5818 emitcode ("mov", "c,acc.7"); // c = A
5820 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5822 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5824 emitcode ("anl", "a,#0x%02x",
5825 SRMask[shCount]); // 0000000A:BBBBBBBC
5827 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5828 emitcode ("orl", "a,#0x%02x",
5829 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5831 emitcode ("", "%05d$:", tlbl->key + 100);
5838 /*-----------------------------------------------------------------*/
5839 /* shiftL2Left2Result - shift left two bytes from left to result */
5840 /*-----------------------------------------------------------------*/
5842 shiftL2Left2Result (operand * left, int offl,
5843 operand * result, int offr, int shCount)
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 /* ax << shCount (x = lsb(result)) */
5858 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5859 aopPut (AOP (result), "a", offr + MSB16);
5863 /*-----------------------------------------------------------------*/
5864 /* shiftR2Left2Result - shift right two bytes from left to result */
5865 /*-----------------------------------------------------------------*/
5867 shiftR2Left2Result (operand * left, int offl,
5868 operand * result, int offr,
5869 int shCount, int sign)
5871 if (sameRegs (AOP (result), AOP (left)) &&
5872 ((offl + MSB16) == offr))
5874 /* don't crash result[offr] */
5875 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5876 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5880 movLeft2Result (left, offl, result, offr, 0);
5881 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5883 /* a:x >> shCount (x = lsb(result)) */
5885 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5887 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5888 if (getDataSize (result) > 1)
5889 aopPut (AOP (result), "a", offr + MSB16);
5892 /*-----------------------------------------------------------------*/
5893 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5894 /*-----------------------------------------------------------------*/
5896 shiftLLeftOrResult (operand * left, int offl,
5897 operand * result, int offr, int shCount)
5899 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5900 /* shift left accumulator */
5902 /* or with result */
5903 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5904 /* back to result */
5905 aopPut (AOP (result), "a", offr);
5908 /*-----------------------------------------------------------------*/
5909 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5910 /*-----------------------------------------------------------------*/
5912 shiftRLeftOrResult (operand * left, int offl,
5913 operand * result, int offr, int shCount)
5915 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5916 /* shift right accumulator */
5918 /* or with result */
5919 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5920 /* back to result */
5921 aopPut (AOP (result), "a", offr);
5924 /*-----------------------------------------------------------------*/
5925 /* genlshOne - left shift a one byte quantity by known count */
5926 /*-----------------------------------------------------------------*/
5928 genlshOne (operand * result, operand * left, int shCount)
5930 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5933 /*-----------------------------------------------------------------*/
5934 /* genlshTwo - left shift two bytes by known amount != 0 */
5935 /*-----------------------------------------------------------------*/
5937 genlshTwo (operand * result, operand * left, int shCount)
5941 size = getDataSize (result);
5943 /* if shCount >= 8 */
5951 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5953 movLeft2Result (left, LSB, result, MSB16, 0);
5955 aopPut (AOP (result), zero, LSB);
5958 /* 1 <= shCount <= 7 */
5962 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5964 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5968 /*-----------------------------------------------------------------*/
5969 /* shiftLLong - shift left one long from left to result */
5970 /* offl = LSB or MSB16 */
5971 /*-----------------------------------------------------------------*/
5973 shiftLLong (operand * left, operand * result, int offr)
5976 int size = AOP_SIZE (result);
5978 if (size >= LSB + offr)
5980 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5982 emitcode ("add", "a,acc");
5983 if (sameRegs (AOP (left), AOP (result)) &&
5984 size >= MSB16 + offr && offr != LSB)
5985 emitcode ("xch", "a,%s",
5986 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5988 aopPut (AOP (result), "a", LSB + offr);
5991 if (size >= MSB16 + offr)
5993 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5995 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5998 emitcode ("rlc", "a");
5999 if (sameRegs (AOP (left), AOP (result)) &&
6000 size >= MSB24 + offr && offr != LSB)
6001 emitcode ("xch", "a,%s",
6002 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6004 aopPut (AOP (result), "a", MSB16 + offr);
6007 if (size >= MSB24 + offr)
6009 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6011 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6014 emitcode ("rlc", "a");
6015 if (sameRegs (AOP (left), AOP (result)) &&
6016 size >= MSB32 + offr && offr != LSB)
6017 emitcode ("xch", "a,%s",
6018 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6020 aopPut (AOP (result), "a", MSB24 + offr);
6023 if (size > MSB32 + offr)
6025 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6027 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6030 emitcode ("rlc", "a");
6031 aopPut (AOP (result), "a", MSB32 + offr);
6034 aopPut (AOP (result), zero, LSB);
6037 /*-----------------------------------------------------------------*/
6038 /* genlshFour - shift four byte by a known amount != 0 */
6039 /*-----------------------------------------------------------------*/
6041 genlshFour (operand * result, operand * left, int shCount)
6045 size = AOP_SIZE (result);
6047 /* if shifting more that 3 bytes */
6052 /* lowest order of left goes to the highest
6053 order of the destination */
6054 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6056 movLeft2Result (left, LSB, result, MSB32, 0);
6057 aopPut (AOP (result), zero, LSB);
6058 aopPut (AOP (result), zero, MSB16);
6059 aopPut (AOP (result), zero, MSB24);
6063 /* more than two bytes */
6064 else if (shCount >= 16)
6066 /* lower order two bytes goes to higher order two bytes */
6068 /* if some more remaining */
6070 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6073 movLeft2Result (left, MSB16, result, MSB32, 0);
6074 movLeft2Result (left, LSB, result, MSB24, 0);
6076 aopPut (AOP (result), zero, MSB16);
6077 aopPut (AOP (result), zero, LSB);
6081 /* if more than 1 byte */
6082 else if (shCount >= 8)
6084 /* lower order three bytes goes to higher order three bytes */
6089 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6091 movLeft2Result (left, LSB, result, MSB16, 0);
6097 movLeft2Result (left, MSB24, result, MSB32, 0);
6098 movLeft2Result (left, MSB16, result, MSB24, 0);
6099 movLeft2Result (left, LSB, result, MSB16, 0);
6100 aopPut (AOP (result), zero, LSB);
6102 else if (shCount == 1)
6103 shiftLLong (left, result, MSB16);
6106 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6107 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6108 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6109 aopPut (AOP (result), zero, LSB);
6114 /* 1 <= shCount <= 7 */
6115 else if (shCount <= 2)
6117 shiftLLong (left, result, LSB);
6119 shiftLLong (result, result, LSB);
6121 /* 3 <= shCount <= 7, optimize */
6124 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6125 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6126 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6130 /*-----------------------------------------------------------------*/
6131 /* genLeftShiftLiteral - left shifting by known count */
6132 /*-----------------------------------------------------------------*/
6134 genLeftShiftLiteral (operand * left,
6139 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6142 freeAsmop (right, NULL, ic, TRUE);
6144 aopOp (left, ic, FALSE);
6145 aopOp (result, ic, FALSE);
6147 size = getSize (operandType (result));
6150 emitcode ("; shift left ", "result %d, left %d", size,
6154 /* I suppose that the left size >= result size */
6159 movLeft2Result (left, size, result, size, 0);
6163 else if (shCount >= (size * 8))
6165 aopPut (AOP (result), zero, size);
6171 genlshOne (result, left, shCount);
6175 genlshTwo (result, left, shCount);
6179 genlshFour (result, left, shCount);
6182 fprintf(stderr, "*** ack! mystery literal shift!\n");
6186 freeAsmop (left, NULL, ic, TRUE);
6187 freeAsmop (result, NULL, ic, TRUE);
6190 /*-----------------------------------------------------------------*/
6191 /* genLeftShift - generates code for left shifting */
6192 /*-----------------------------------------------------------------*/
6194 genLeftShift (iCode * ic)
6196 operand *left, *right, *result;
6199 symbol *tlbl, *tlbl1;
6201 right = IC_RIGHT (ic);
6202 left = IC_LEFT (ic);
6203 result = IC_RESULT (ic);
6205 aopOp (right, ic, FALSE);
6207 /* if the shift count is known then do it
6208 as efficiently as possible */
6209 if (AOP_TYPE (right) == AOP_LIT)
6211 genLeftShiftLiteral (left, right, result, ic);
6215 /* shift count is unknown then we have to form
6216 a loop get the loop count in B : Note: we take
6217 only the lower order byte since shifting
6218 more that 32 bits make no sense anyway, ( the
6219 largest size of an object can be only 32 bits ) */
6221 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6222 emitcode ("inc", "b");
6223 freeAsmop (right, NULL, ic, TRUE);
6224 aopOp (left, ic, FALSE);
6225 aopOp (result, ic, FALSE);
6227 /* now move the left to the result if they are not the
6229 if (!sameRegs (AOP (left), AOP (result)) &&
6230 AOP_SIZE (result) > 1)
6233 size = AOP_SIZE (result);
6237 l = aopGet (AOP (left), offset, FALSE, TRUE);
6238 if (*l == '@' && (IS_AOP_PREG (result)))
6241 emitcode ("mov", "a,%s", l);
6242 aopPut (AOP (result), "a", offset);
6245 aopPut (AOP (result), l, offset);
6250 tlbl = newiTempLabel (NULL);
6251 size = AOP_SIZE (result);
6253 tlbl1 = newiTempLabel (NULL);
6255 /* if it is only one byte then */
6258 symbol *tlbl1 = newiTempLabel (NULL);
6260 l = aopGet (AOP (left), 0, FALSE, FALSE);
6262 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6263 emitcode ("", "%05d$:", tlbl->key + 100);
6264 emitcode ("add", "a,acc");
6265 emitcode ("", "%05d$:", tlbl1->key + 100);
6266 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6267 aopPut (AOP (result), "a", 0);
6271 reAdjustPreg (AOP (result));
6273 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6274 emitcode ("", "%05d$:", tlbl->key + 100);
6275 l = aopGet (AOP (result), offset, FALSE, FALSE);
6277 emitcode ("add", "a,acc");
6278 aopPut (AOP (result), "a", offset++);
6281 l = aopGet (AOP (result), offset, FALSE, FALSE);
6283 emitcode ("rlc", "a");
6284 aopPut (AOP (result), "a", offset++);
6286 reAdjustPreg (AOP (result));
6288 emitcode ("", "%05d$:", tlbl1->key + 100);
6289 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6291 freeAsmop (left, NULL, ic, TRUE);
6292 freeAsmop (result, NULL, ic, TRUE);
6295 /*-----------------------------------------------------------------*/
6296 /* genrshOne - right shift a one byte quantity by known count */
6297 /*-----------------------------------------------------------------*/
6299 genrshOne (operand * result, operand * left,
6300 int shCount, int sign)
6302 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6305 /*-----------------------------------------------------------------*/
6306 /* genrshTwo - right shift two bytes by known amount != 0 */
6307 /*-----------------------------------------------------------------*/
6309 genrshTwo (operand * result, operand * left,
6310 int shCount, int sign)
6312 /* if shCount >= 8 */
6317 shiftR1Left2Result (left, MSB16, result, LSB,
6320 movLeft2Result (left, MSB16, result, LSB, sign);
6321 addSign (result, MSB16, sign);
6324 /* 1 <= shCount <= 7 */
6326 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6329 /*-----------------------------------------------------------------*/
6330 /* shiftRLong - shift right one long from left to result */
6331 /* offl = LSB or MSB16 */
6332 /*-----------------------------------------------------------------*/
6334 shiftRLong (operand * left, int offl,
6335 operand * result, int sign)
6337 int isSameRegs=sameRegs(AOP(left),AOP(result));
6339 if (isSameRegs && offl>1) {
6340 // we are in big trouble, but this shouldn't happen
6341 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6344 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6349 emitcode ("rlc", "a");
6350 emitcode ("subb", "a,acc");
6351 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6353 aopPut (AOP(result), zero, MSB32);
6358 emitcode ("clr", "c");
6360 emitcode ("mov", "c,acc.7");
6363 emitcode ("rrc", "a");
6365 if (isSameRegs && offl==MSB16) {
6366 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6368 aopPut (AOP (result), "a", MSB32);
6369 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6372 emitcode ("rrc", "a");
6373 if (isSameRegs && offl==1) {
6374 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6376 aopPut (AOP (result), "a", MSB24);
6377 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6379 emitcode ("rrc", "a");
6380 aopPut (AOP (result), "a", MSB16 - offl);
6384 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6385 emitcode ("rrc", "a");
6386 aopPut (AOP (result), "a", LSB);
6390 /*-----------------------------------------------------------------*/
6391 /* genrshFour - shift four byte by a known amount != 0 */
6392 /*-----------------------------------------------------------------*/
6394 genrshFour (operand * result, operand * left,
6395 int shCount, int sign)
6397 /* if shifting more that 3 bytes */
6402 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6404 movLeft2Result (left, MSB32, result, LSB, sign);
6405 addSign (result, MSB16, sign);
6407 else if (shCount >= 16)
6411 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6414 movLeft2Result (left, MSB24, result, LSB, 0);
6415 movLeft2Result (left, MSB32, result, MSB16, sign);
6417 addSign (result, MSB24, sign);
6419 else if (shCount >= 8)
6423 shiftRLong (left, MSB16, result, sign);
6424 else if (shCount == 0)
6426 movLeft2Result (left, MSB16, result, LSB, 0);
6427 movLeft2Result (left, MSB24, result, MSB16, 0);
6428 movLeft2Result (left, MSB32, result, MSB24, sign);
6429 addSign (result, MSB32, sign);
6433 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6434 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6435 /* the last shift is signed */
6436 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6437 addSign (result, MSB32, sign);
6441 { /* 1 <= shCount <= 7 */
6444 shiftRLong (left, LSB, result, sign);
6446 shiftRLong (result, LSB, result, sign);
6450 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6451 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6452 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6457 /*-----------------------------------------------------------------*/
6458 /* genRightShiftLiteral - right shifting by known count */
6459 /*-----------------------------------------------------------------*/
6461 genRightShiftLiteral (operand * left,
6467 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6470 freeAsmop (right, NULL, ic, TRUE);
6472 aopOp (left, ic, FALSE);
6473 aopOp (result, ic, FALSE);
6476 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6480 size = getDataSize (left);
6481 /* test the LEFT size !!! */
6483 /* I suppose that the left size >= result size */
6486 size = getDataSize (result);
6488 movLeft2Result (left, size, result, size, 0);
6491 else if (shCount >= (size * 8))
6494 /* get sign in acc.7 */
6495 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6496 addSign (result, LSB, sign);
6503 genrshOne (result, left, shCount, sign);
6507 genrshTwo (result, left, shCount, sign);
6511 genrshFour (result, left, shCount, sign);
6517 freeAsmop (left, NULL, ic, TRUE);
6518 freeAsmop (result, NULL, ic, TRUE);
6522 /*-----------------------------------------------------------------*/
6523 /* genSignedRightShift - right shift of signed number */
6524 /*-----------------------------------------------------------------*/
6526 genSignedRightShift (iCode * ic)
6528 operand *right, *left, *result;
6531 symbol *tlbl, *tlbl1;
6533 /* we do it the hard way put the shift count in b
6534 and loop thru preserving the sign */
6536 right = IC_RIGHT (ic);
6537 left = IC_LEFT (ic);
6538 result = IC_RESULT (ic);
6540 aopOp (right, ic, FALSE);
6543 if (AOP_TYPE (right) == AOP_LIT)
6545 genRightShiftLiteral (left, right, result, ic, 1);
6548 /* shift count is unknown then we have to form
6549 a loop get the loop count in B : Note: we take
6550 only the lower order byte since shifting
6551 more that 32 bits make no sense anyway, ( the
6552 largest size of an object can be only 32 bits ) */
6554 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6555 emitcode ("inc", "b");
6556 freeAsmop (right, NULL, ic, TRUE);
6557 aopOp (left, ic, FALSE);
6558 aopOp (result, ic, FALSE);
6560 /* now move the left to the result if they are not the
6562 if (!sameRegs (AOP (left), AOP (result)) &&
6563 AOP_SIZE (result) > 1)
6566 size = AOP_SIZE (result);
6570 l = aopGet (AOP (left), offset, FALSE, TRUE);
6571 if (*l == '@' && IS_AOP_PREG (result))
6574 emitcode ("mov", "a,%s", l);
6575 aopPut (AOP (result), "a", offset);
6578 aopPut (AOP (result), l, offset);
6583 /* mov the highest order bit to OVR */
6584 tlbl = newiTempLabel (NULL);
6585 tlbl1 = newiTempLabel (NULL);
6587 size = AOP_SIZE (result);
6589 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6590 emitcode ("rlc", "a");
6591 emitcode ("mov", "ov,c");
6592 /* if it is only one byte then */
6595 l = aopGet (AOP (left), 0, FALSE, FALSE);
6597 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6598 emitcode ("", "%05d$:", tlbl->key + 100);
6599 emitcode ("mov", "c,ov");
6600 emitcode ("rrc", "a");
6601 emitcode ("", "%05d$:", tlbl1->key + 100);
6602 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6603 aopPut (AOP (result), "a", 0);
6607 reAdjustPreg (AOP (result));
6608 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6609 emitcode ("", "%05d$:", tlbl->key + 100);
6610 emitcode ("mov", "c,ov");
6613 l = aopGet (AOP (result), offset, FALSE, FALSE);
6615 emitcode ("rrc", "a");
6616 aopPut (AOP (result), "a", offset--);
6618 reAdjustPreg (AOP (result));
6619 emitcode ("", "%05d$:", tlbl1->key + 100);
6620 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6623 freeAsmop (left, NULL, ic, TRUE);
6624 freeAsmop (result, NULL, ic, TRUE);
6627 /*-----------------------------------------------------------------*/
6628 /* genRightShift - generate code for right shifting */
6629 /*-----------------------------------------------------------------*/
6631 genRightShift (iCode * ic)
6633 operand *right, *left, *result;
6637 symbol *tlbl, *tlbl1;
6639 /* if signed then we do it the hard way preserve the
6640 sign bit moving it inwards */
6641 retype = getSpec (operandType (IC_RESULT (ic)));
6643 if (!SPEC_USIGN (retype))
6645 genSignedRightShift (ic);
6649 /* signed & unsigned types are treated the same : i.e. the
6650 signed is NOT propagated inwards : quoting from the
6651 ANSI - standard : "for E1 >> E2, is equivalent to division
6652 by 2**E2 if unsigned or if it has a non-negative value,
6653 otherwise the result is implementation defined ", MY definition
6654 is that the sign does not get propagated */
6656 right = IC_RIGHT (ic);
6657 left = IC_LEFT (ic);
6658 result = IC_RESULT (ic);
6660 aopOp (right, ic, FALSE);
6662 /* if the shift count is known then do it
6663 as efficiently as possible */
6664 if (AOP_TYPE (right) == AOP_LIT)
6666 genRightShiftLiteral (left, right, result, ic, 0);
6670 /* shift count is unknown then we have to form
6671 a loop get the loop count in B : Note: we take
6672 only the lower order byte since shifting
6673 more that 32 bits make no sense anyway, ( the
6674 largest size of an object can be only 32 bits ) */
6676 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6677 emitcode ("inc", "b");
6678 freeAsmop (right, NULL, ic, TRUE);
6679 aopOp (left, ic, FALSE);
6680 aopOp (result, ic, FALSE);
6682 /* now move the left to the result if they are not the
6684 if (!sameRegs (AOP (left), AOP (result)) &&
6685 AOP_SIZE (result) > 1)
6688 size = AOP_SIZE (result);
6692 l = aopGet (AOP (left), offset, FALSE, TRUE);
6693 if (*l == '@' && IS_AOP_PREG (result))
6696 emitcode ("mov", "a,%s", l);
6697 aopPut (AOP (result), "a", offset);
6700 aopPut (AOP (result), l, offset);
6705 tlbl = newiTempLabel (NULL);
6706 tlbl1 = newiTempLabel (NULL);
6707 size = AOP_SIZE (result);
6710 /* if it is only one byte then */
6713 l = aopGet (AOP (left), 0, FALSE, FALSE);
6715 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6716 emitcode ("", "%05d$:", tlbl->key + 100);
6718 emitcode ("rrc", "a");
6719 emitcode ("", "%05d$:", tlbl1->key + 100);
6720 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6721 aopPut (AOP (result), "a", 0);
6725 reAdjustPreg (AOP (result));
6726 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6727 emitcode ("", "%05d$:", tlbl->key + 100);
6731 l = aopGet (AOP (result), offset, FALSE, FALSE);
6733 emitcode ("rrc", "a");
6734 aopPut (AOP (result), "a", offset--);
6736 reAdjustPreg (AOP (result));
6738 emitcode ("", "%05d$:", tlbl1->key + 100);
6739 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6742 freeAsmop (left, NULL, ic, TRUE);
6743 freeAsmop (result, NULL, ic, TRUE);
6746 /*-----------------------------------------------------------------*/
6747 /* genUnpackBits - generates code for unpacking bits */
6748 /*-----------------------------------------------------------------*/
6750 genUnpackBits (operand * result, char *rname, int ptype)
6758 etype = getSpec (operandType (result));
6759 rsize = getSize (operandType (result));
6760 /* read the first byte */
6766 emitcode ("mov", "a,@%s", rname);
6770 emitcode ("movx", "a,@%s", rname);
6774 emitcode ("movx", "a,@dptr");
6778 emitcode ("clr", "a");
6779 emitcode ("movc", "a,%s", "@a+dptr");
6783 emitcode ("lcall", "__gptrget");
6787 rlen = SPEC_BLEN (etype);
6789 /* if we have bitdisplacement then it fits */
6790 /* into this byte completely or if length is */
6791 /* less than a byte */
6792 if ((shCnt = SPEC_BSTR (etype)) ||
6793 (SPEC_BLEN (etype) <= 8))
6796 /* shift right acc */
6799 emitcode ("anl", "a,#0x%02x",
6800 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6801 aopPut (AOP (result), "a", offset++);
6805 /* bit field did not fit in a byte */
6806 aopPut (AOP (result), "a", offset++);
6815 emitcode ("inc", "%s", rname);
6816 emitcode ("mov", "a,@%s", rname);
6820 emitcode ("inc", "%s", rname);
6821 emitcode ("movx", "a,@%s", rname);
6825 emitcode ("inc", "dptr");
6826 emitcode ("movx", "a,@dptr");
6830 emitcode ("clr", "a");
6831 emitcode ("inc", "dptr");
6832 emitcode ("movc", "a", "@a+dptr");
6836 emitcode ("inc", "dptr");
6837 emitcode ("lcall", "__gptrget");
6842 /* if we are done */
6846 aopPut (AOP (result), "a", offset++);
6852 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6854 aopPut (AOP (result), "a", offset++);
6862 aopPut (AOP (result), zero, offset++);
6868 /*-----------------------------------------------------------------*/
6869 /* genDataPointerGet - generates code when ptr offset is known */
6870 /*-----------------------------------------------------------------*/
6872 genDataPointerGet (operand * left,
6878 int size, offset = 0;
6879 aopOp (result, ic, TRUE);
6881 /* get the string representation of the name */
6882 l = aopGet (AOP (left), 0, FALSE, TRUE);
6883 size = AOP_SIZE (result);
6887 sprintf (buffer, "(%s + %d)", l + 1, offset);
6889 sprintf (buffer, "%s", l + 1);
6890 aopPut (AOP (result), buffer, offset++);
6893 freeAsmop (left, NULL, ic, TRUE);
6894 freeAsmop (result, NULL, ic, TRUE);
6897 /*-----------------------------------------------------------------*/
6898 /* genNearPointerGet - emitcode for near pointer fetch */
6899 /*-----------------------------------------------------------------*/
6901 genNearPointerGet (operand * left,
6909 sym_link *rtype, *retype;
6910 sym_link *ltype = operandType (left);
6913 rtype = operandType (result);
6914 retype = getSpec (rtype);
6916 aopOp (left, ic, FALSE);
6918 /* if left is rematerialisable and
6919 result is not bit variable type and
6920 the left is pointer to data space i.e
6921 lower 128 bytes of space */
6922 if (AOP_TYPE (left) == AOP_IMMD &&
6923 !IS_BITVAR (retype) &&
6924 DCL_TYPE (ltype) == POINTER)
6926 genDataPointerGet (left, result, ic);
6930 /* if the value is already in a pointer register
6931 then don't need anything more */
6932 if (!AOP_INPREG (AOP (left)))
6934 /* otherwise get a free pointer register */
6936 preg = getFreePtr (ic, &aop, FALSE);
6937 emitcode ("mov", "%s,%s",
6939 aopGet (AOP (left), 0, FALSE, TRUE));
6943 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6945 aopOp (result, ic, FALSE);
6947 /* if bitfield then unpack the bits */
6948 if (IS_BITVAR (retype))
6949 genUnpackBits (result, rname, POINTER);
6952 /* we have can just get the values */
6953 int size = AOP_SIZE (result);
6958 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6961 emitcode ("mov", "a,@%s", rname);
6962 aopPut (AOP (result), "a", offset);
6966 sprintf (buffer, "@%s", rname);
6967 aopPut (AOP (result), buffer, offset);
6971 emitcode ("inc", "%s", rname);
6975 /* now some housekeeping stuff */
6976 if (aop) /* we had to allocate for this iCode */
6978 if (pi) { /* post increment present */
6979 aopPut(AOP ( left ),rname,0);
6981 freeAsmop (NULL, aop, ic, TRUE);
6985 /* we did not allocate which means left
6986 already in a pointer register, then
6987 if size > 0 && this could be used again
6988 we have to point it back to where it
6990 if ((AOP_SIZE (result) > 1 &&
6991 !OP_SYMBOL (left)->remat &&
6992 (OP_SYMBOL (left)->liveTo > ic->seq ||
6996 int size = AOP_SIZE (result) - 1;
6998 emitcode ("dec", "%s", rname);
7003 freeAsmop (left, NULL, ic, TRUE);
7004 freeAsmop (result, NULL, ic, TRUE);
7005 if (pi) pi->generated = 1;
7008 /*-----------------------------------------------------------------*/
7009 /* genPagedPointerGet - emitcode for paged pointer fetch */
7010 /*-----------------------------------------------------------------*/
7012 genPagedPointerGet (operand * left,
7020 sym_link *rtype, *retype;
7022 rtype = operandType (result);
7023 retype = getSpec (rtype);
7025 aopOp (left, ic, FALSE);
7027 /* if the value is already in a pointer register
7028 then don't need anything more */
7029 if (!AOP_INPREG (AOP (left)))
7031 /* otherwise get a free pointer register */
7033 preg = getFreePtr (ic, &aop, FALSE);
7034 emitcode ("mov", "%s,%s",
7036 aopGet (AOP (left), 0, FALSE, TRUE));
7040 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7042 aopOp (result, ic, FALSE);
7044 /* if bitfield then unpack the bits */
7045 if (IS_BITVAR (retype))
7046 genUnpackBits (result, rname, PPOINTER);
7049 /* we have can just get the values */
7050 int size = AOP_SIZE (result);
7056 emitcode ("movx", "a,@%s", rname);
7057 aopPut (AOP (result), "a", offset);
7062 emitcode ("inc", "%s", rname);
7066 /* now some housekeeping stuff */
7067 if (aop) /* we had to allocate for this iCode */
7069 if (pi) aopPut ( AOP (left), rname, 0);
7070 freeAsmop (NULL, aop, ic, TRUE);
7074 /* we did not allocate which means left
7075 already in a pointer register, then
7076 if size > 0 && this could be used again
7077 we have to point it back to where it
7079 if ((AOP_SIZE (result) > 1 &&
7080 !OP_SYMBOL (left)->remat &&
7081 (OP_SYMBOL (left)->liveTo > ic->seq ||
7085 int size = AOP_SIZE (result) - 1;
7087 emitcode ("dec", "%s", rname);
7092 freeAsmop (left, NULL, ic, TRUE);
7093 freeAsmop (result, NULL, ic, TRUE);
7094 if (pi) pi->generated = 1;
7098 /*-----------------------------------------------------------------*/
7099 /* genFarPointerGet - gget value from far space */
7100 /*-----------------------------------------------------------------*/
7102 genFarPointerGet (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", FPOINTER);
7131 size = AOP_SIZE (result);
7136 emitcode ("movx", "a,@dptr");
7137 aopPut (AOP (result), "a", offset++);
7139 emitcode ("inc", "dptr");
7143 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7144 aopPut ( AOP (left), "dpl", 0);
7145 aopPut ( AOP (left), "dph", 1);
7148 freeAsmop (left, NULL, ic, TRUE);
7149 freeAsmop (result, NULL, ic, TRUE);
7152 /*-----------------------------------------------------------------*/
7153 /* genCodePointerGet - gget value from code space */
7154 /*-----------------------------------------------------------------*/
7156 genCodePointerGet (operand * left,
7157 operand * result, iCode * ic, iCode *pi)
7160 sym_link *retype = getSpec (operandType (result));
7162 aopOp (left, ic, FALSE);
7164 /* if the operand is already in dptr
7165 then we do nothing else we move the value to dptr */
7166 if (AOP_TYPE (left) != AOP_STR)
7168 /* if this is remateriazable */
7169 if (AOP_TYPE (left) == AOP_IMMD)
7170 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7172 { /* we need to get it byte by byte */
7173 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7174 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7177 /* so dptr know contains the address */
7178 aopOp (result, ic, FALSE);
7180 /* if bit then unpack */
7181 if (IS_BITVAR (retype))
7182 genUnpackBits (result, "dptr", CPOINTER);
7185 size = AOP_SIZE (result);
7190 emitcode ("clr", "a");
7191 emitcode ("movc", "a,@a+dptr");
7192 aopPut (AOP (result), "a", offset++);
7194 emitcode ("inc", "dptr");
7198 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7199 aopPut ( AOP (left), "dpl", 0);
7200 aopPut ( AOP (left), "dph", 1);
7203 freeAsmop (left, NULL, ic, TRUE);
7204 freeAsmop (result, NULL, ic, TRUE);
7207 /*-----------------------------------------------------------------*/
7208 /* genGenPointerGet - gget value from generic pointer space */
7209 /*-----------------------------------------------------------------*/
7211 genGenPointerGet (operand * left,
7212 operand * result, iCode * ic, iCode *pi)
7215 sym_link *retype = getSpec (operandType (result));
7217 aopOp (left, ic, FALSE);
7219 /* if the operand is already in dptr
7220 then we do nothing else we move the value to dptr */
7221 if (AOP_TYPE (left) != AOP_STR)
7223 /* if this is remateriazable */
7224 if (AOP_TYPE (left) == AOP_IMMD)
7226 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7227 emitcode ("mov", "b,#%d", pointerCode (retype));
7230 { /* we need to get it byte by byte */
7231 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7232 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7233 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7236 /* so dptr know contains the address */
7237 aopOp (result, ic, FALSE);
7239 /* if bit then unpack */
7240 if (IS_BITVAR (retype))
7241 genUnpackBits (result, "dptr", GPOINTER);
7244 size = AOP_SIZE (result);
7249 emitcode ("lcall", "__gptrget");
7250 aopPut (AOP (result), "a", offset++);
7252 emitcode ("inc", "dptr");
7256 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7257 aopPut ( AOP (left), "dpl", 0);
7258 aopPut ( AOP (left), "dph", 1);
7261 freeAsmop (left, NULL, ic, TRUE);
7262 freeAsmop (result, NULL, ic, TRUE);
7265 /*-----------------------------------------------------------------*/
7266 /* genPointerGet - generate code for pointer get */
7267 /*-----------------------------------------------------------------*/
7269 genPointerGet (iCode * ic, iCode *pi)
7271 operand *left, *result;
7272 sym_link *type, *etype;
7275 left = IC_LEFT (ic);
7276 result = IC_RESULT (ic);
7278 /* depending on the type of pointer we need to
7279 move it to the correct pointer register */
7280 type = operandType (left);
7281 etype = getSpec (type);
7282 /* if left is of type of pointer then it is simple */
7283 if (IS_PTR (type) && !IS_FUNC (type->next))
7284 p_type = DCL_TYPE (type);
7287 /* we have to go by the storage class */
7288 p_type = PTR_TYPE (SPEC_OCLS (etype));
7291 /* now that we have the pointer type we assign
7292 the pointer values */
7298 genNearPointerGet (left, result, ic, pi);
7302 genPagedPointerGet (left, result, ic, pi);
7306 genFarPointerGet (left, result, ic, pi);
7310 genCodePointerGet (left, result, ic, pi);
7314 genGenPointerGet (left, result, ic, pi);
7320 /*-----------------------------------------------------------------*/
7321 /* genPackBits - generates code for packed bit storage */
7322 /*-----------------------------------------------------------------*/
7324 genPackBits (sym_link * etype,
7326 char *rname, int p_type)
7334 blen = SPEC_BLEN (etype);
7335 bstr = SPEC_BSTR (etype);
7337 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7340 /* if the bit lenth is less than or */
7341 /* it exactly fits a byte then */
7342 if (SPEC_BLEN (etype) <= 8)
7344 shCount = SPEC_BSTR (etype);
7346 /* shift left acc */
7349 if (SPEC_BLEN (etype) < 8)
7350 { /* if smaller than a byte */
7356 emitcode ("mov", "b,a");
7357 emitcode ("mov", "a,@%s", rname);
7361 emitcode ("mov", "b,a");
7362 emitcode ("movx", "a,@dptr");
7366 emitcode ("push", "b");
7367 emitcode ("push", "acc");
7368 emitcode ("lcall", "__gptrget");
7369 emitcode ("pop", "b");
7373 emitcode ("anl", "a,#0x%02x", (unsigned char)
7374 ((unsigned char) (0xFF << (blen + bstr)) |
7375 (unsigned char) (0xFF >> (8 - bstr))));
7376 emitcode ("orl", "a,b");
7377 if (p_type == GPOINTER)
7378 emitcode ("pop", "b");
7385 emitcode ("mov", "@%s,a", rname);
7389 emitcode ("movx", "@dptr,a");
7393 emitcode ("lcall", "__gptrput");
7398 if (SPEC_BLEN (etype) <= 8)
7401 emitcode ("inc", "%s", rname);
7402 rLen = SPEC_BLEN (etype);
7404 /* now generate for lengths greater than one byte */
7408 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7420 emitcode ("mov", "@%s,a", rname);
7423 emitcode ("mov", "@%s,%s", rname, l);
7428 emitcode ("movx", "@dptr,a");
7433 emitcode ("lcall", "__gptrput");
7436 emitcode ("inc", "%s", rname);
7441 /* last last was not complete */
7444 /* save the byte & read byte */
7448 emitcode ("mov", "b,a");
7449 emitcode ("mov", "a,@%s", rname);
7453 emitcode ("mov", "b,a");
7454 emitcode ("movx", "a,@dptr");
7458 emitcode ("push", "b");
7459 emitcode ("push", "acc");
7460 emitcode ("lcall", "__gptrget");
7461 emitcode ("pop", "b");
7465 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7466 emitcode ("orl", "a,b");
7469 if (p_type == GPOINTER)
7470 emitcode ("pop", "b");
7476 emitcode ("mov", "@%s,a", rname);
7480 emitcode ("movx", "@dptr,a");
7484 emitcode ("lcall", "__gptrput");
7488 /*-----------------------------------------------------------------*/
7489 /* genDataPointerSet - remat pointer to data space */
7490 /*-----------------------------------------------------------------*/
7492 genDataPointerSet (operand * right,
7496 int size, offset = 0;
7497 char *l, buffer[256];
7499 aopOp (right, ic, FALSE);
7501 l = aopGet (AOP (result), 0, FALSE, TRUE);
7502 size = AOP_SIZE (right);
7506 sprintf (buffer, "(%s + %d)", l + 1, offset);
7508 sprintf (buffer, "%s", l + 1);
7509 emitcode ("mov", "%s,%s", buffer,
7510 aopGet (AOP (right), offset++, FALSE, FALSE));
7513 freeAsmop (right, NULL, ic, TRUE);
7514 freeAsmop (result, NULL, ic, TRUE);
7517 /*-----------------------------------------------------------------*/
7518 /* genNearPointerSet - emitcode for near pointer put */
7519 /*-----------------------------------------------------------------*/
7521 genNearPointerSet (operand * right,
7529 sym_link *retype, *letype;
7530 sym_link *ptype = operandType (result);
7532 retype = getSpec (operandType (right));
7533 letype = getSpec (ptype);
7534 aopOp (result, ic, FALSE);
7536 /* if the result is rematerializable &
7537 in data space & not a bit variable */
7538 if (AOP_TYPE (result) == AOP_IMMD &&
7539 DCL_TYPE (ptype) == POINTER &&
7540 !IS_BITVAR (retype) &&
7541 !IS_BITVAR (letype))
7543 genDataPointerSet (right, result, ic);
7547 /* if the value is already in a pointer register
7548 then don't need anything more */
7549 if (!AOP_INPREG (AOP (result)))
7551 /* otherwise get a free pointer register */
7553 preg = getFreePtr (ic, &aop, FALSE);
7554 emitcode ("mov", "%s,%s",
7556 aopGet (AOP (result), 0, FALSE, TRUE));
7560 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7562 aopOp (right, ic, FALSE);
7564 /* if bitfield then unpack the bits */
7565 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7566 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7569 /* we have can just get the values */
7570 int size = AOP_SIZE (right);
7575 l = aopGet (AOP (right), offset, FALSE, TRUE);
7579 emitcode ("mov", "@%s,a", rname);
7582 emitcode ("mov", "@%s,%s", rname, l);
7584 emitcode ("inc", "%s", rname);
7589 /* now some housekeeping stuff */
7590 if (aop) /* we had to allocate for this iCode */
7592 if (pi) aopPut (AOP (result),rname,0);
7593 freeAsmop (NULL, aop, ic, TRUE);
7597 /* we did not allocate which means left
7598 already in a pointer register, then
7599 if size > 0 && this could be used again
7600 we have to point it back to where it
7602 if ((AOP_SIZE (right) > 1 &&
7603 !OP_SYMBOL (result)->remat &&
7604 (OP_SYMBOL (result)->liveTo > ic->seq ||
7608 int size = AOP_SIZE (right) - 1;
7610 emitcode ("dec", "%s", rname);
7615 if (pi) pi->generated = 1;
7616 freeAsmop (result, NULL, ic, TRUE);
7617 freeAsmop (right, NULL, ic, TRUE);
7620 /*-----------------------------------------------------------------*/
7621 /* genPagedPointerSet - emitcode for Paged pointer put */
7622 /*-----------------------------------------------------------------*/
7624 genPagedPointerSet (operand * right,
7632 sym_link *retype, *letype;
7634 retype = getSpec (operandType (right));
7635 letype = getSpec (operandType (result));
7637 aopOp (result, ic, FALSE);
7639 /* if the value is already in a pointer register
7640 then don't need anything more */
7641 if (!AOP_INPREG (AOP (result)))
7643 /* otherwise get a free pointer register */
7645 preg = getFreePtr (ic, &aop, FALSE);
7646 emitcode ("mov", "%s,%s",
7648 aopGet (AOP (result), 0, FALSE, TRUE));
7652 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7654 aopOp (right, ic, FALSE);
7656 /* if bitfield then unpack the bits */
7657 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7658 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7661 /* we have can just get the values */
7662 int size = AOP_SIZE (right);
7667 l = aopGet (AOP (right), offset, FALSE, TRUE);
7670 emitcode ("movx", "@%s,a", rname);
7673 emitcode ("inc", "%s", rname);
7679 /* now some housekeeping stuff */
7680 if (aop) /* we had to allocate for this iCode */
7682 if (pi) aopPut (AOP (result),rname,0);
7683 freeAsmop (NULL, aop, ic, TRUE);
7687 /* we did not allocate which means left
7688 already in a pointer register, then
7689 if size > 0 && this could be used again
7690 we have to point it back to where it
7692 if (AOP_SIZE (right) > 1 &&
7693 !OP_SYMBOL (result)->remat &&
7694 (OP_SYMBOL (result)->liveTo > ic->seq ||
7697 int size = AOP_SIZE (right) - 1;
7699 emitcode ("dec", "%s", rname);
7704 if (pi) pi->generated = 1;
7705 freeAsmop (result, NULL, ic, TRUE);
7706 freeAsmop (right, NULL, ic, TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genFarPointerSet - set value from far space */
7713 /*-----------------------------------------------------------------*/
7715 genFarPointerSet (operand * right,
7716 operand * result, iCode * ic, iCode * pi)
7719 sym_link *retype = getSpec (operandType (right));
7720 sym_link *letype = getSpec (operandType (result));
7721 aopOp (result, ic, FALSE);
7723 /* if the operand is already in dptr
7724 then we do nothing else we move the value to dptr */
7725 if (AOP_TYPE (result) != AOP_STR)
7727 /* if this is remateriazable */
7728 if (AOP_TYPE (result) == AOP_IMMD)
7729 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7731 { /* we need to get it byte by byte */
7732 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7733 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7736 /* so dptr know contains the address */
7737 aopOp (right, ic, FALSE);
7739 /* if bit then unpack */
7740 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7741 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7744 size = AOP_SIZE (right);
7749 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7751 emitcode ("movx", "@dptr,a");
7753 emitcode ("inc", "dptr");
7756 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7757 aopPut (AOP(result),"dpl",0);
7758 aopPut (AOP(result),"dph",1);
7761 freeAsmop (result, NULL, ic, TRUE);
7762 freeAsmop (right, NULL, ic, TRUE);
7765 /*-----------------------------------------------------------------*/
7766 /* genGenPointerSet - set value from generic pointer space */
7767 /*-----------------------------------------------------------------*/
7769 genGenPointerSet (operand * right,
7770 operand * result, iCode * ic, iCode * pi)
7773 sym_link *retype = getSpec (operandType (right));
7774 sym_link *letype = getSpec (operandType (result));
7776 aopOp (result, ic, FALSE);
7778 /* if the operand is already in dptr
7779 then we do nothing else we move the value to dptr */
7780 if (AOP_TYPE (result) != AOP_STR)
7782 /* if this is remateriazable */
7783 if (AOP_TYPE (result) == AOP_IMMD)
7785 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7786 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7789 { /* we need to get it byte by byte */
7790 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7791 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7792 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7795 /* so dptr know contains the address */
7796 aopOp (right, ic, FALSE);
7798 /* if bit then unpack */
7799 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7800 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7803 size = AOP_SIZE (right);
7808 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7810 emitcode ("lcall", "__gptrput");
7812 emitcode ("inc", "dptr");
7816 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7817 aopPut (AOP(result),"dpl",0);
7818 aopPut (AOP(result),"dph",1);
7821 freeAsmop (result, NULL, ic, TRUE);
7822 freeAsmop (right, NULL, ic, TRUE);
7825 /*-----------------------------------------------------------------*/
7826 /* genPointerSet - stores the value into a pointer location */
7827 /*-----------------------------------------------------------------*/
7829 genPointerSet (iCode * ic, iCode *pi)
7831 operand *right, *result;
7832 sym_link *type, *etype;
7835 right = IC_RIGHT (ic);
7836 result = IC_RESULT (ic);
7838 /* depending on the type of pointer we need to
7839 move it to the correct pointer register */
7840 type = operandType (result);
7841 etype = getSpec (type);
7842 /* if left is of type of pointer then it is simple */
7843 if (IS_PTR (type) && !IS_FUNC (type->next))
7845 p_type = DCL_TYPE (type);
7849 /* we have to go by the storage class */
7850 p_type = PTR_TYPE (SPEC_OCLS (etype));
7853 /* now that we have the pointer type we assign
7854 the pointer values */
7860 genNearPointerSet (right, result, ic, pi);
7864 genPagedPointerSet (right, result, ic, pi);
7868 genFarPointerSet (right, result, ic, pi);
7872 genGenPointerSet (right, result, ic, pi);
7878 /*-----------------------------------------------------------------*/
7879 /* genIfx - generate code for Ifx statement */
7880 /*-----------------------------------------------------------------*/
7882 genIfx (iCode * ic, iCode * popIc)
7884 operand *cond = IC_COND (ic);
7887 aopOp (cond, ic, FALSE);
7889 /* get the value into acc */
7890 if (AOP_TYPE (cond) != AOP_CRY)
7894 /* the result is now in the accumulator */
7895 freeAsmop (cond, NULL, ic, TRUE);
7897 /* if there was something to be popped then do it */
7901 /* if the condition is a bit variable */
7902 if (isbit && IS_ITEMP (cond) &&
7904 genIfxJump (ic, SPIL_LOC (cond)->rname);
7905 else if (isbit && !IS_ITEMP (cond))
7906 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7908 genIfxJump (ic, "a");
7913 /*-----------------------------------------------------------------*/
7914 /* genAddrOf - generates code for address of */
7915 /*-----------------------------------------------------------------*/
7917 genAddrOf (iCode * ic)
7919 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7922 aopOp (IC_RESULT (ic), ic, FALSE);
7924 /* if the operand is on the stack then we
7925 need to get the stack offset of this
7929 /* if it has an offset then we need to compute
7933 emitcode ("mov", "a,_bp");
7934 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7935 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7939 /* we can just move _bp */
7940 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7942 /* fill the result with zero */
7943 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7948 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7954 /* object not on stack then we need the name */
7955 size = AOP_SIZE (IC_RESULT (ic));
7960 char s[SDCC_NAME_MAX];
7962 sprintf (s, "#(%s >> %d)",
7966 sprintf (s, "#%s", sym->rname);
7967 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7971 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genFarFarAssign - assignment when both are in far space */
7977 /*-----------------------------------------------------------------*/
7979 genFarFarAssign (operand * result, operand * right, iCode * ic)
7981 int size = AOP_SIZE (right);
7984 /* first push the right side on to the stack */
7987 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7989 emitcode ("push", "acc");
7992 freeAsmop (right, NULL, ic, FALSE);
7993 /* now assign DPTR to result */
7994 aopOp (result, ic, FALSE);
7995 size = AOP_SIZE (result);
7998 emitcode ("pop", "acc");
7999 aopPut (AOP (result), "a", --offset);
8001 freeAsmop (result, NULL, ic, FALSE);
8005 /*-----------------------------------------------------------------*/
8006 /* genAssign - generate code for assignment */
8007 /*-----------------------------------------------------------------*/
8009 genAssign (iCode * ic)
8011 operand *result, *right;
8013 unsigned long lit = 0L;
8015 result = IC_RESULT (ic);
8016 right = IC_RIGHT (ic);
8018 /* if they are the same */
8019 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8022 aopOp (right, ic, FALSE);
8024 /* special case both in far space */
8025 if (AOP_TYPE (right) == AOP_DPTR &&
8026 IS_TRUE_SYMOP (result) &&
8027 isOperandInFarSpace (result))
8030 genFarFarAssign (result, right, ic);
8034 aopOp (result, ic, TRUE);
8036 /* if they are the same registers */
8037 if (sameRegs (AOP (right), AOP (result)))
8040 /* if the result is a bit */
8041 if (AOP_TYPE (result) == AOP_CRY)
8044 /* if the right size is a literal then
8045 we know what the value is */
8046 if (AOP_TYPE (right) == AOP_LIT)
8048 if (((int) operandLitValue (right)))
8049 aopPut (AOP (result), one, 0);
8051 aopPut (AOP (result), zero, 0);
8055 /* the right is also a bit variable */
8056 if (AOP_TYPE (right) == AOP_CRY)
8058 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8059 aopPut (AOP (result), "c", 0);
8065 aopPut (AOP (result), "a", 0);
8069 /* bit variables done */
8071 size = AOP_SIZE (result);
8073 if (AOP_TYPE (right) == AOP_LIT)
8074 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8076 (AOP_TYPE (result) != AOP_REG) &&
8077 (AOP_TYPE (right) == AOP_LIT) &&
8078 !IS_FLOAT (operandType (right)) &&
8081 emitcode ("clr", "a");
8084 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8085 aopPut (AOP (result), "a", size);
8087 aopPut (AOP (result),
8088 aopGet (AOP (right), size, FALSE, FALSE),
8096 aopPut (AOP (result),
8097 aopGet (AOP (right), offset, FALSE, FALSE),
8104 freeAsmop (right, NULL, ic, TRUE);
8105 freeAsmop (result, NULL, ic, TRUE);
8108 /*-----------------------------------------------------------------*/
8109 /* genJumpTab - genrates code for jump table */
8110 /*-----------------------------------------------------------------*/
8112 genJumpTab (iCode * ic)
8117 aopOp (IC_JTCOND (ic), ic, FALSE);
8118 /* get the condition into accumulator */
8119 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8121 /* multiply by three */
8122 emitcode ("add", "a,acc");
8123 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8124 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8126 jtab = newiTempLabel (NULL);
8127 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8128 emitcode ("jmp", "@a+dptr");
8129 emitcode ("", "%05d$:", jtab->key + 100);
8130 /* now generate the jump labels */
8131 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8132 jtab = setNextItem (IC_JTLABELS (ic)))
8133 emitcode ("ljmp", "%05d$", jtab->key + 100);
8137 /*-----------------------------------------------------------------*/
8138 /* genCast - gen code for casting */
8139 /*-----------------------------------------------------------------*/
8141 genCast (iCode * ic)
8143 operand *result = IC_RESULT (ic);
8144 sym_link *ctype = operandType (IC_LEFT (ic));
8145 sym_link *rtype = operandType (IC_RIGHT (ic));
8146 operand *right = IC_RIGHT (ic);
8149 /* if they are equivalent then do nothing */
8150 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8153 aopOp (right, ic, FALSE);
8154 aopOp (result, ic, FALSE);
8156 /* if the result is a bit */
8157 if (AOP_TYPE (result) == AOP_CRY)
8159 /* if the right size is a literal then
8160 we know what the value is */
8161 if (AOP_TYPE (right) == AOP_LIT)
8163 if (((int) operandLitValue (right)))
8164 aopPut (AOP (result), one, 0);
8166 aopPut (AOP (result), zero, 0);
8171 /* the right is also a bit variable */
8172 if (AOP_TYPE (right) == AOP_CRY)
8174 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8175 aopPut (AOP (result), "c", 0);
8181 aopPut (AOP (result), "a", 0);
8185 /* if they are the same size : or less */
8186 if (AOP_SIZE (result) <= AOP_SIZE (right))
8189 /* if they are in the same place */
8190 if (sameRegs (AOP (right), AOP (result)))
8193 /* if they in different places then copy */
8194 size = AOP_SIZE (result);
8198 aopPut (AOP (result),
8199 aopGet (AOP (right), offset, FALSE, FALSE),
8207 /* if the result is of type pointer */
8212 sym_link *type = operandType (right);
8213 sym_link *etype = getSpec (type);
8215 /* pointer to generic pointer */
8216 if (IS_GENPTR (ctype))
8221 p_type = DCL_TYPE (type);
8224 if (SPEC_SCLS(etype)==S_REGISTER) {
8225 // let's assume it is a generic pointer
8228 /* we have to go by the storage class */
8229 p_type = PTR_TYPE (SPEC_OCLS (etype));
8233 /* the first two bytes are known */
8234 size = GPTRSIZE - 1;
8238 aopPut (AOP (result),
8239 aopGet (AOP (right), offset, FALSE, FALSE),
8243 /* the last byte depending on type */
8259 case PPOINTER: // what the fck is this?
8264 /* this should never happen */
8265 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8266 "got unknown pointer type");
8269 aopPut (AOP (result), l, GPTRSIZE - 1);
8273 /* just copy the pointers */
8274 size = AOP_SIZE (result);
8278 aopPut (AOP (result),
8279 aopGet (AOP (right), offset, FALSE, FALSE),
8286 /* so we now know that the size of destination is greater
8287 than the size of the source */
8288 /* we move to result for the size of source */
8289 size = AOP_SIZE (right);
8293 aopPut (AOP (result),
8294 aopGet (AOP (right), offset, FALSE, FALSE),
8299 /* now depending on the sign of the source && destination */
8300 size = AOP_SIZE (result) - AOP_SIZE (right);
8301 /* if unsigned or not an integral type */
8302 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8305 aopPut (AOP (result), zero, offset++);
8309 /* we need to extend the sign :{ */
8310 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8313 emitcode ("rlc", "a");
8314 emitcode ("subb", "a,acc");
8316 aopPut (AOP (result), "a", offset++);
8319 /* we are done hurray !!!! */
8322 freeAsmop (right, NULL, ic, TRUE);
8323 freeAsmop (result, NULL, ic, TRUE);
8327 /*-----------------------------------------------------------------*/
8328 /* genDjnz - generate decrement & jump if not zero instrucion */
8329 /*-----------------------------------------------------------------*/
8331 genDjnz (iCode * ic, iCode * ifx)
8337 /* if the if condition has a false label
8338 then we cannot save */
8342 /* if the minus is not of the form
8344 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8345 !IS_OP_LITERAL (IC_RIGHT (ic)))
8348 if (operandLitValue (IC_RIGHT (ic)) != 1)
8351 /* if the size of this greater than one then no
8353 if (getSize (operandType (IC_RESULT (ic))) > 1)
8356 /* otherwise we can save BIG */
8357 lbl = newiTempLabel (NULL);
8358 lbl1 = newiTempLabel (NULL);
8360 aopOp (IC_RESULT (ic), ic, FALSE);
8362 if (AOP_NEEDSACC(IC_RESULT(ic)))
8364 /* If the result is accessed indirectly via
8365 * the accumulator, we must explicitly write
8366 * it back after the decrement.
8368 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8370 if (strcmp(rByte, "a"))
8372 /* Something is hopelessly wrong */
8373 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8374 __FILE__, __LINE__);
8375 /* We can just give up; the generated code will be inefficient,
8378 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8381 emitcode ("dec", "%s", rByte);
8382 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8383 emitcode ("jnz", "%05d$", lbl->key + 100);
8385 else if (IS_AOP_PREG (IC_RESULT (ic)))
8387 emitcode ("dec", "%s",
8388 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8389 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8390 emitcode ("jnz", "%05d$", lbl->key + 100);
8394 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8397 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8398 emitcode ("", "%05d$:", lbl->key + 100);
8399 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8400 emitcode ("", "%05d$:", lbl1->key + 100);
8402 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8407 /*-----------------------------------------------------------------*/
8408 /* genReceive - generate code for a receive iCode */
8409 /*-----------------------------------------------------------------*/
8411 genReceive (iCode * ic)
8413 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8414 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8415 IS_TRUE_SYMOP (IC_RESULT (ic))))
8418 int size = getSize (operandType (IC_RESULT (ic)));
8419 int offset = fReturnSizeMCS51 - size;
8422 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8423 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8426 aopOp (IC_RESULT (ic), ic, FALSE);
8427 size = AOP_SIZE (IC_RESULT (ic));
8431 emitcode ("pop", "acc");
8432 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8439 aopOp (IC_RESULT (ic), ic, FALSE);
8441 assignResultValue (IC_RESULT (ic));
8444 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8447 /*-----------------------------------------------------------------*/
8448 /* gen51Code - generate code for 8051 based controllers */
8449 /*-----------------------------------------------------------------*/
8451 gen51Code (iCode * lic)
8456 lineHead = lineCurr = NULL;
8458 /* print the allocation information */
8460 printAllocInfo (currFunc, codeOutFile);
8461 /* if debug information required */
8462 /* if (options.debug && currFunc) { */
8463 if (options.debug && currFunc)
8465 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8467 if (IS_STATIC (currFunc->etype))
8468 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8470 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8473 /* stack pointer name */
8474 if (options.useXstack)
8480 for (ic = lic; ic; ic = ic->next)
8483 if (cln != ic->lineno)
8488 emitcode ("", "C$%s$%d$%d$%d ==.",
8489 FileBaseName (ic->filename), ic->lineno,
8490 ic->level, ic->block);
8493 emitcode (";", "%s %d", ic->filename, ic->lineno);
8496 /* if the result is marked as
8497 spilt and rematerializable or code for
8498 this has already been generated then
8500 if (resultRemat (ic) || ic->generated)
8503 /* depending on the operation */
8523 /* IPOP happens only when trying to restore a
8524 spilt live range, if there is an ifx statement
8525 following this pop then the if statement might
8526 be using some of the registers being popped which
8527 would destory the contents of the register so
8528 we need to check for this condition and handle it */
8530 ic->next->op == IFX &&
8531 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8532 genIfx (ic->next, ic);
8550 genEndFunction (ic);
8570 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8587 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8591 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8598 /* note these two are xlated by algebraic equivalence
8599 during parsing SDCC.y */
8600 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8601 "got '>=' or '<=' shouldn't have come here");
8605 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8617 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8621 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8625 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8652 case GET_VALUE_AT_ADDRESS:
8653 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8657 if (POINTER_SET (ic))
8658 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8684 addSet (&_G.sendSet, ic);
8693 /* now we are ready to call the
8694 peep hole optimizer */
8695 if (!options.nopeep)
8696 peepHole (&lineHead);
8698 /* now do the actual printing */
8699 printLine (lineHead, codeOutFile);