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 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4600 emitcode ("anl", "a,%s",
4601 aopGet (AOP (left), offset, FALSE, FALSE));
4603 emitcode ("jnz", "%05d$", tlbl->key + 100);
4609 emitcode ("", "%05d$:", tlbl->key + 100);
4613 jmpTrueOrFalse (ifx, tlbl);
4617 for (; (size--); offset++)
4620 // result = left & right
4621 if (AOP_TYPE (right) == AOP_LIT)
4623 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4625 aopPut (AOP (result),
4626 aopGet (AOP (left), offset, FALSE, FALSE),
4630 else if (bytelit == 0)
4632 aopPut (AOP (result), zero, offset);
4636 // faster than result <- left, anl result,right
4637 // and better if result is SFR
4638 if (AOP_TYPE (left) == AOP_ACC)
4639 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4642 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4643 emitcode ("anl", "a,%s",
4644 aopGet (AOP (left), offset, FALSE, FALSE));
4646 aopPut (AOP (result), "a", offset);
4652 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4653 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4654 freeAsmop (result, NULL, ic, TRUE);
4657 /*-----------------------------------------------------------------*/
4658 /* genOr - code for or */
4659 /*-----------------------------------------------------------------*/
4661 genOr (iCode * ic, iCode * ifx)
4663 operand *left, *right, *result;
4664 int size, offset = 0;
4665 unsigned long lit = 0L;
4667 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4668 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4669 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4672 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4674 AOP_TYPE (left), AOP_TYPE (right));
4675 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4677 AOP_SIZE (left), AOP_SIZE (right));
4680 /* if left is a literal & right is not then exchange them */
4681 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4682 AOP_NEEDSACC (left))
4684 operand *tmp = right;
4689 /* if result = right then exchange them */
4690 if (sameRegs (AOP (result), AOP (right)))
4692 operand *tmp = right;
4697 /* if right is bit then exchange them */
4698 if (AOP_TYPE (right) == AOP_CRY &&
4699 AOP_TYPE (left) != AOP_CRY)
4701 operand *tmp = right;
4705 if (AOP_TYPE (right) == AOP_LIT)
4706 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4708 size = AOP_SIZE (result);
4712 if (AOP_TYPE (left) == AOP_CRY)
4714 if (AOP_TYPE (right) == AOP_LIT)
4716 // c = bit & literal;
4719 // lit != 0 => result = 1
4720 if (AOP_TYPE (result) == AOP_CRY)
4723 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4725 continueIfTrue (ifx);
4728 emitcode ("setb", "c");
4732 // lit == 0 => result = left
4733 if (size && sameRegs (AOP (result), AOP (left)))
4735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4740 if (AOP_TYPE (right) == AOP_CRY)
4743 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4744 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4749 symbol *tlbl = newiTempLabel (NULL);
4750 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4751 emitcode ("setb", "c");
4752 emitcode ("jb", "%s,%05d$",
4753 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4755 emitcode ("jnz", "%05d$", tlbl->key + 100);
4756 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4758 jmpTrueOrFalse (ifx, tlbl);
4764 emitcode ("", "%05d$:", tlbl->key + 100);
4773 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4774 genIfxJump (ifx, "c");
4778 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4779 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4780 if ((AOP_TYPE (right) == AOP_LIT) &&
4781 (AOP_TYPE (result) == AOP_CRY) &&
4782 (AOP_TYPE (left) != AOP_CRY))
4788 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4790 continueIfTrue (ifx);
4795 // lit = 0, result = boolean(left)
4797 emitcode ("setb", "c");
4801 symbol *tlbl = newiTempLabel (NULL);
4802 emitcode ("jnz", "%05d$", tlbl->key + 100);
4804 emitcode ("", "%05d$:", tlbl->key + 100);
4808 genIfxJump (ifx, "a");
4816 /* if left is same as result */
4817 if (sameRegs (AOP (result), AOP (left)))
4819 for (; size--; offset++)
4821 if (AOP_TYPE (right) == AOP_LIT)
4823 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4825 else if (IS_AOP_PREG (left))
4827 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4828 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4829 aopPut (AOP (result), "a", offset);
4832 emitcode ("orl", "%s,%s",
4833 aopGet (AOP (left), offset, FALSE, TRUE),
4834 aopGet (AOP (right), offset, FALSE, FALSE));
4838 if (AOP_TYPE (left) == AOP_ACC)
4839 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4842 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4843 if (IS_AOP_PREG (left))
4845 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4846 aopPut (AOP (result), "a", offset);
4849 emitcode ("orl", "%s,a",
4850 aopGet (AOP (left), offset, FALSE, TRUE));
4857 // left & result in different registers
4858 if (AOP_TYPE (result) == AOP_CRY)
4861 // if(size), result in bit
4862 // if(!size && ifx), conditional oper: if(left | right)
4863 symbol *tlbl = newiTempLabel (NULL);
4864 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4866 emitcode ("setb", "c");
4869 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4870 emitcode ("orl", "a,%s",
4871 aopGet (AOP (right), offset, FALSE, FALSE));
4873 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4874 emitcode ("orl", "a,%s",
4875 aopGet (AOP (left), offset, FALSE, FALSE));
4877 emitcode ("jnz", "%05d$", tlbl->key + 100);
4883 emitcode ("", "%05d$:", tlbl->key + 100);
4887 jmpTrueOrFalse (ifx, tlbl);
4890 for (; (size--); offset++)
4893 // result = left & right
4894 if (AOP_TYPE (right) == AOP_LIT)
4896 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4898 aopPut (AOP (result),
4899 aopGet (AOP (left), offset, FALSE, FALSE),
4904 // faster than result <- left, anl result,right
4905 // and better if result is SFR
4906 if (AOP_TYPE (left) == AOP_ACC)
4907 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4910 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4911 emitcode ("orl", "a,%s",
4912 aopGet (AOP (left), offset, FALSE, FALSE));
4914 aopPut (AOP (result), "a", offset);
4919 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4920 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4921 freeAsmop (result, NULL, ic, TRUE);
4924 /*-----------------------------------------------------------------*/
4925 /* genXor - code for xclusive or */
4926 /*-----------------------------------------------------------------*/
4928 genXor (iCode * ic, iCode * ifx)
4930 operand *left, *right, *result;
4931 int size, offset = 0;
4932 unsigned long lit = 0L;
4934 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4935 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4936 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4939 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4941 AOP_TYPE (left), AOP_TYPE (right));
4942 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4944 AOP_SIZE (left), AOP_SIZE (right));
4947 /* if left is a literal & right is not ||
4948 if left needs acc & right does not */
4949 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4950 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4952 operand *tmp = right;
4957 /* if result = right then exchange them */
4958 if (sameRegs (AOP (result), AOP (right)))
4960 operand *tmp = right;
4965 /* if right is bit then exchange them */
4966 if (AOP_TYPE (right) == AOP_CRY &&
4967 AOP_TYPE (left) != AOP_CRY)
4969 operand *tmp = right;
4973 if (AOP_TYPE (right) == AOP_LIT)
4974 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4976 size = AOP_SIZE (result);
4980 if (AOP_TYPE (left) == AOP_CRY)
4982 if (AOP_TYPE (right) == AOP_LIT)
4984 // c = bit & literal;
4987 // lit>>1 != 0 => result = 1
4988 if (AOP_TYPE (result) == AOP_CRY)
4991 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4993 continueIfTrue (ifx);
4996 emitcode ("setb", "c");
5003 // lit == 0, result = left
5004 if (size && sameRegs (AOP (result), AOP (left)))
5006 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5010 // lit == 1, result = not(left)
5011 if (size && sameRegs (AOP (result), AOP (left)))
5013 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5019 emitcode ("cpl", "c");
5028 symbol *tlbl = newiTempLabel (NULL);
5029 if (AOP_TYPE (right) == AOP_CRY)
5032 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5036 int sizer = AOP_SIZE (right);
5038 // if val>>1 != 0, result = 1
5039 emitcode ("setb", "c");
5042 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5044 // test the msb of the lsb
5045 emitcode ("anl", "a,#0xfe");
5046 emitcode ("jnz", "%05d$", tlbl->key + 100);
5050 emitcode ("rrc", "a");
5052 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5053 emitcode ("cpl", "c");
5054 emitcode ("", "%05d$:", (tlbl->key + 100));
5061 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5062 genIfxJump (ifx, "c");
5066 if (sameRegs (AOP (result), AOP (left)))
5068 /* if left is same as result */
5069 for (; size--; offset++)
5071 if (AOP_TYPE (right) == AOP_LIT)
5073 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5075 else if (IS_AOP_PREG (left))
5077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5078 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5079 aopPut (AOP (result), "a", offset);
5082 emitcode ("xrl", "%s,%s",
5083 aopGet (AOP (left), offset, FALSE, TRUE),
5084 aopGet (AOP (right), offset, FALSE, FALSE));
5088 if (AOP_TYPE (left) == AOP_ACC)
5089 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5092 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5093 if (IS_AOP_PREG (left))
5095 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5096 aopPut (AOP (result), "a", offset);
5099 emitcode ("xrl", "%s,a",
5100 aopGet (AOP (left), offset, FALSE, TRUE));
5107 // left & result in different registers
5108 if (AOP_TYPE (result) == AOP_CRY)
5111 // if(size), result in bit
5112 // if(!size && ifx), conditional oper: if(left ^ right)
5113 symbol *tlbl = newiTempLabel (NULL);
5114 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5116 emitcode ("setb", "c");
5119 if ((AOP_TYPE (right) == AOP_LIT) &&
5120 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5126 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5127 emitcode ("xrl", "a,%s",
5128 aopGet (AOP (right), offset, FALSE, FALSE));
5130 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5131 emitcode ("xrl", "a,%s",
5132 aopGet (AOP (left), offset, FALSE, FALSE));
5135 emitcode ("jnz", "%05d$", tlbl->key + 100);
5141 emitcode ("", "%05d$:", tlbl->key + 100);
5145 jmpTrueOrFalse (ifx, tlbl);
5148 for (; (size--); offset++)
5151 // result = left & right
5152 if (AOP_TYPE (right) == AOP_LIT)
5154 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5156 aopPut (AOP (result),
5157 aopGet (AOP (left), offset, FALSE, FALSE),
5162 // faster than result <- left, anl result,right
5163 // and better if result is SFR
5164 if (AOP_TYPE (left) == AOP_ACC)
5165 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5168 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5169 emitcode ("xrl", "a,%s",
5170 aopGet (AOP (left), offset, FALSE, TRUE));
5172 aopPut (AOP (result), "a", offset);
5177 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5178 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179 freeAsmop (result, NULL, ic, TRUE);
5182 /*-----------------------------------------------------------------*/
5183 /* genInline - write the inline code out */
5184 /*-----------------------------------------------------------------*/
5186 genInline (iCode * ic)
5188 char *buffer, *bp, *bp1;
5190 _G.inLine += (!options.asmpeep);
5192 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5193 strcpy (buffer, IC_INLINE (ic));
5195 /* emit each line as a code */
5220 /* emitcode("",buffer); */
5221 _G.inLine -= (!options.asmpeep);
5224 /*-----------------------------------------------------------------*/
5225 /* genRRC - rotate right with carry */
5226 /*-----------------------------------------------------------------*/
5230 operand *left, *result;
5231 int size, offset = 0;
5234 /* rotate right with carry */
5235 left = IC_LEFT (ic);
5236 result = IC_RESULT (ic);
5237 aopOp (left, ic, FALSE);
5238 aopOp (result, ic, FALSE);
5240 /* move it to the result */
5241 size = AOP_SIZE (result);
5246 l = aopGet (AOP (left), offset, FALSE, FALSE);
5248 emitcode ("rrc", "a");
5249 if (AOP_SIZE (result) > 1)
5250 aopPut (AOP (result), "a", offset--);
5252 /* now we need to put the carry into the
5253 highest order byte of the result */
5254 if (AOP_SIZE (result) > 1)
5256 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5259 emitcode ("mov", "acc.7,c");
5260 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5261 freeAsmop (left, NULL, ic, TRUE);
5262 freeAsmop (result, NULL, ic, TRUE);
5265 /*-----------------------------------------------------------------*/
5266 /* genRLC - generate code for rotate left with carry */
5267 /*-----------------------------------------------------------------*/
5271 operand *left, *result;
5272 int size, offset = 0;
5275 /* rotate right with carry */
5276 left = IC_LEFT (ic);
5277 result = IC_RESULT (ic);
5278 aopOp (left, ic, FALSE);
5279 aopOp (result, ic, FALSE);
5281 /* move it to the result */
5282 size = AOP_SIZE (result);
5286 l = aopGet (AOP (left), offset, FALSE, FALSE);
5288 emitcode ("add", "a,acc");
5289 if (AOP_SIZE (result) > 1)
5290 aopPut (AOP (result), "a", offset++);
5293 l = aopGet (AOP (left), offset, FALSE, FALSE);
5295 emitcode ("rlc", "a");
5296 if (AOP_SIZE (result) > 1)
5297 aopPut (AOP (result), "a", offset++);
5300 /* now we need to put the carry into the
5301 highest order byte of the result */
5302 if (AOP_SIZE (result) > 1)
5304 l = aopGet (AOP (result), 0, FALSE, FALSE);
5307 emitcode ("mov", "acc.0,c");
5308 aopPut (AOP (result), "a", 0);
5309 freeAsmop (left, NULL, ic, TRUE);
5310 freeAsmop (result, NULL, ic, TRUE);
5313 /*-----------------------------------------------------------------*/
5314 /* genGetHbit - generates code get highest order bit */
5315 /*-----------------------------------------------------------------*/
5317 genGetHbit (iCode * ic)
5319 operand *left, *result;
5320 left = IC_LEFT (ic);
5321 result = IC_RESULT (ic);
5322 aopOp (left, ic, FALSE);
5323 aopOp (result, ic, FALSE);
5325 /* get the highest order byte into a */
5326 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5327 if (AOP_TYPE (result) == AOP_CRY)
5329 emitcode ("rlc", "a");
5334 emitcode ("rl", "a");
5335 emitcode ("anl", "a,#0x01");
5340 freeAsmop (left, NULL, ic, TRUE);
5341 freeAsmop (result, NULL, ic, TRUE);
5344 /*-----------------------------------------------------------------*/
5345 /* AccRol - rotate left accumulator by known count */
5346 /*-----------------------------------------------------------------*/
5348 AccRol (int shCount)
5350 shCount &= 0x0007; // shCount : 0..7
5357 emitcode ("rl", "a");
5360 emitcode ("rl", "a");
5361 emitcode ("rl", "a");
5364 emitcode ("swap", "a");
5365 emitcode ("rr", "a");
5368 emitcode ("swap", "a");
5371 emitcode ("swap", "a");
5372 emitcode ("rl", "a");
5375 emitcode ("rr", "a");
5376 emitcode ("rr", "a");
5379 emitcode ("rr", "a");
5384 /*-----------------------------------------------------------------*/
5385 /* AccLsh - left shift accumulator by known count */
5386 /*-----------------------------------------------------------------*/
5388 AccLsh (int shCount)
5393 emitcode ("add", "a,acc");
5394 else if (shCount == 2)
5396 emitcode ("add", "a,acc");
5397 emitcode ("add", "a,acc");
5401 /* rotate left accumulator */
5403 /* and kill the lower order bits */
5404 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5409 /*-----------------------------------------------------------------*/
5410 /* AccRsh - right shift accumulator by known count */
5411 /*-----------------------------------------------------------------*/
5413 AccRsh (int shCount)
5420 emitcode ("rrc", "a");
5424 /* rotate right accumulator */
5425 AccRol (8 - shCount);
5426 /* and kill the higher order bits */
5427 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5432 /*-----------------------------------------------------------------*/
5433 /* AccSRsh - signed right shift accumulator by known count */
5434 /*-----------------------------------------------------------------*/
5436 AccSRsh (int shCount)
5443 emitcode ("mov", "c,acc.7");
5444 emitcode ("rrc", "a");
5446 else if (shCount == 2)
5448 emitcode ("mov", "c,acc.7");
5449 emitcode ("rrc", "a");
5450 emitcode ("mov", "c,acc.7");
5451 emitcode ("rrc", "a");
5455 tlbl = newiTempLabel (NULL);
5456 /* rotate right accumulator */
5457 AccRol (8 - shCount);
5458 /* and kill the higher order bits */
5459 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5460 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5461 emitcode ("orl", "a,#0x%02x",
5462 (unsigned char) ~SRMask[shCount]);
5463 emitcode ("", "%05d$:", tlbl->key + 100);
5468 /*-----------------------------------------------------------------*/
5469 /* shiftR1Left2Result - shift right one byte from left to result */
5470 /*-----------------------------------------------------------------*/
5472 shiftR1Left2Result (operand * left, int offl,
5473 operand * result, int offr,
5474 int shCount, int sign)
5476 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5477 /* shift right accumulator */
5482 aopPut (AOP (result), "a", offr);
5485 /*-----------------------------------------------------------------*/
5486 /* shiftL1Left2Result - shift left one byte from left to result */
5487 /*-----------------------------------------------------------------*/
5489 shiftL1Left2Result (operand * left, int offl,
5490 operand * result, int offr, int shCount)
5493 l = aopGet (AOP (left), offl, FALSE, FALSE);
5495 /* shift left accumulator */
5497 aopPut (AOP (result), "a", offr);
5500 /*-----------------------------------------------------------------*/
5501 /* movLeft2Result - move byte from left to result */
5502 /*-----------------------------------------------------------------*/
5504 movLeft2Result (operand * left, int offl,
5505 operand * result, int offr, int sign)
5508 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5510 l = aopGet (AOP (left), offl, FALSE, FALSE);
5512 if (*l == '@' && (IS_AOP_PREG (result)))
5514 emitcode ("mov", "a,%s", l);
5515 aopPut (AOP (result), "a", offr);
5520 aopPut (AOP (result), l, offr);
5523 /* MSB sign in acc.7 ! */
5524 if (getDataSize (left) == offl + 1)
5526 emitcode ("mov", "a,%s", l);
5527 aopPut (AOP (result), "a", offr);
5534 /*-----------------------------------------------------------------*/
5535 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5536 /*-----------------------------------------------------------------*/
5540 emitcode ("rrc", "a");
5541 emitcode ("xch", "a,%s", x);
5542 emitcode ("rrc", "a");
5543 emitcode ("xch", "a,%s", x);
5546 /*-----------------------------------------------------------------*/
5547 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5548 /*-----------------------------------------------------------------*/
5552 emitcode ("xch", "a,%s", x);
5553 emitcode ("rlc", "a");
5554 emitcode ("xch", "a,%s", x);
5555 emitcode ("rlc", "a");
5558 /*-----------------------------------------------------------------*/
5559 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5560 /*-----------------------------------------------------------------*/
5564 emitcode ("xch", "a,%s", x);
5565 emitcode ("add", "a,acc");
5566 emitcode ("xch", "a,%s", x);
5567 emitcode ("rlc", "a");
5570 /*-----------------------------------------------------------------*/
5571 /* AccAXLsh - left shift a:x by known count (0..7) */
5572 /*-----------------------------------------------------------------*/
5574 AccAXLsh (char *x, int shCount)
5589 case 5: // AAAAABBB:CCCCCDDD
5591 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5593 emitcode ("anl", "a,#0x%02x",
5594 SLMask[shCount]); // BBB00000:CCCCCDDD
5596 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5598 AccRol (shCount); // DDDCCCCC:BBB00000
5600 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5602 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5604 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5606 emitcode ("anl", "a,#0x%02x",
5607 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5609 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5611 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5614 case 6: // AAAAAABB:CCCCCCDD
5615 emitcode ("anl", "a,#0x%02x",
5616 SRMask[shCount]); // 000000BB:CCCCCCDD
5617 emitcode ("mov", "c,acc.0"); // c = B
5618 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5620 AccAXRrl1 (x); // BCCCCCCD:D000000B
5621 AccAXRrl1 (x); // BBCCCCCC:DD000000
5623 emitcode("rrc","a");
5624 emitcode("xch","a,%s", x);
5625 emitcode("rrc","a");
5626 emitcode("mov","c,acc.0"); //<< get correct bit
5627 emitcode("xch","a,%s", x);
5629 emitcode("rrc","a");
5630 emitcode("xch","a,%s", x);
5631 emitcode("rrc","a");
5632 emitcode("xch","a,%s", x);
5635 case 7: // a:x <<= 7
5637 emitcode ("anl", "a,#0x%02x",
5638 SRMask[shCount]); // 0000000B:CCCCCCCD
5640 emitcode ("mov", "c,acc.0"); // c = B
5642 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5644 AccAXRrl1 (x); // BCCCCCCC:D0000000
5652 /*-----------------------------------------------------------------*/
5653 /* AccAXRsh - right shift a:x known count (0..7) */
5654 /*-----------------------------------------------------------------*/
5656 AccAXRsh (char *x, int shCount)
5664 AccAXRrl1 (x); // 0->a:x
5669 AccAXRrl1 (x); // 0->a:x
5672 AccAXRrl1 (x); // 0->a:x
5677 case 5: // AAAAABBB:CCCCCDDD = a:x
5679 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5681 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5683 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5685 emitcode ("anl", "a,#0x%02x",
5686 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5688 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5690 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5692 emitcode ("anl", "a,#0x%02x",
5693 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5695 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5697 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5699 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5702 case 6: // AABBBBBB:CCDDDDDD
5704 emitcode ("mov", "c,acc.7");
5705 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5707 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5709 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5711 emitcode ("anl", "a,#0x%02x",
5712 SRMask[shCount]); // 000000AA:BBBBBBCC
5715 case 7: // ABBBBBBB:CDDDDDDD
5717 emitcode ("mov", "c,acc.7"); // c = A
5719 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5721 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5723 emitcode ("anl", "a,#0x%02x",
5724 SRMask[shCount]); // 0000000A:BBBBBBBC
5732 /*-----------------------------------------------------------------*/
5733 /* AccAXRshS - right shift signed a:x known count (0..7) */
5734 /*-----------------------------------------------------------------*/
5736 AccAXRshS (char *x, int shCount)
5744 emitcode ("mov", "c,acc.7");
5745 AccAXRrl1 (x); // s->a:x
5749 emitcode ("mov", "c,acc.7");
5750 AccAXRrl1 (x); // s->a:x
5752 emitcode ("mov", "c,acc.7");
5753 AccAXRrl1 (x); // s->a:x
5758 case 5: // AAAAABBB:CCCCCDDD = a:x
5760 tlbl = newiTempLabel (NULL);
5761 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5763 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5765 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5767 emitcode ("anl", "a,#0x%02x",
5768 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5770 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5772 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5774 emitcode ("anl", "a,#0x%02x",
5775 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5777 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5779 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5781 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5783 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5784 emitcode ("orl", "a,#0x%02x",
5785 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5787 emitcode ("", "%05d$:", tlbl->key + 100);
5788 break; // SSSSAAAA:BBBCCCCC
5790 case 6: // AABBBBBB:CCDDDDDD
5792 tlbl = newiTempLabel (NULL);
5793 emitcode ("mov", "c,acc.7");
5794 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5796 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5798 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5800 emitcode ("anl", "a,#0x%02x",
5801 SRMask[shCount]); // 000000AA:BBBBBBCC
5803 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5804 emitcode ("orl", "a,#0x%02x",
5805 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5807 emitcode ("", "%05d$:", tlbl->key + 100);
5809 case 7: // ABBBBBBB:CDDDDDDD
5811 tlbl = newiTempLabel (NULL);
5812 emitcode ("mov", "c,acc.7"); // c = A
5814 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5816 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5818 emitcode ("anl", "a,#0x%02x",
5819 SRMask[shCount]); // 0000000A:BBBBBBBC
5821 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5822 emitcode ("orl", "a,#0x%02x",
5823 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5825 emitcode ("", "%05d$:", tlbl->key + 100);
5832 /*-----------------------------------------------------------------*/
5833 /* shiftL2Left2Result - shift left two bytes from left to result */
5834 /*-----------------------------------------------------------------*/
5836 shiftL2Left2Result (operand * left, int offl,
5837 operand * result, int offr, int shCount)
5839 if (sameRegs (AOP (result), AOP (left)) &&
5840 ((offl + MSB16) == offr))
5842 /* don't crash result[offr] */
5843 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5844 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5848 movLeft2Result (left, offl, result, offr, 0);
5849 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5851 /* ax << shCount (x = lsb(result)) */
5852 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5853 aopPut (AOP (result), "a", offr + MSB16);
5857 /*-----------------------------------------------------------------*/
5858 /* shiftR2Left2Result - shift right two bytes from left to result */
5859 /*-----------------------------------------------------------------*/
5861 shiftR2Left2Result (operand * left, int offl,
5862 operand * result, int offr,
5863 int shCount, int sign)
5865 if (sameRegs (AOP (result), AOP (left)) &&
5866 ((offl + MSB16) == offr))
5868 /* don't crash result[offr] */
5869 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5870 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5874 movLeft2Result (left, offl, result, offr, 0);
5875 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5877 /* a:x >> shCount (x = lsb(result)) */
5879 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5881 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5882 if (getDataSize (result) > 1)
5883 aopPut (AOP (result), "a", offr + MSB16);
5886 /*-----------------------------------------------------------------*/
5887 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5888 /*-----------------------------------------------------------------*/
5890 shiftLLeftOrResult (operand * left, int offl,
5891 operand * result, int offr, int shCount)
5893 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5894 /* shift left accumulator */
5896 /* or with result */
5897 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5898 /* back to result */
5899 aopPut (AOP (result), "a", offr);
5902 /*-----------------------------------------------------------------*/
5903 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5904 /*-----------------------------------------------------------------*/
5906 shiftRLeftOrResult (operand * left, int offl,
5907 operand * result, int offr, int shCount)
5909 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5910 /* shift right accumulator */
5912 /* or with result */
5913 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5914 /* back to result */
5915 aopPut (AOP (result), "a", offr);
5918 /*-----------------------------------------------------------------*/
5919 /* genlshOne - left shift a one byte quantity by known count */
5920 /*-----------------------------------------------------------------*/
5922 genlshOne (operand * result, operand * left, int shCount)
5924 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5927 /*-----------------------------------------------------------------*/
5928 /* genlshTwo - left shift two bytes by known amount != 0 */
5929 /*-----------------------------------------------------------------*/
5931 genlshTwo (operand * result, operand * left, int shCount)
5935 size = getDataSize (result);
5937 /* if shCount >= 8 */
5945 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5947 movLeft2Result (left, LSB, result, MSB16, 0);
5949 aopPut (AOP (result), zero, LSB);
5952 /* 1 <= shCount <= 7 */
5956 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5958 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5962 /*-----------------------------------------------------------------*/
5963 /* shiftLLong - shift left one long from left to result */
5964 /* offl = LSB or MSB16 */
5965 /*-----------------------------------------------------------------*/
5967 shiftLLong (operand * left, operand * result, int offr)
5970 int size = AOP_SIZE (result);
5972 if (size >= LSB + offr)
5974 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5976 emitcode ("add", "a,acc");
5977 if (sameRegs (AOP (left), AOP (result)) &&
5978 size >= MSB16 + offr && offr != LSB)
5979 emitcode ("xch", "a,%s",
5980 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5982 aopPut (AOP (result), "a", LSB + offr);
5985 if (size >= MSB16 + offr)
5987 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5989 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5992 emitcode ("rlc", "a");
5993 if (sameRegs (AOP (left), AOP (result)) &&
5994 size >= MSB24 + offr && offr != LSB)
5995 emitcode ("xch", "a,%s",
5996 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5998 aopPut (AOP (result), "a", MSB16 + offr);
6001 if (size >= MSB24 + offr)
6003 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6005 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6008 emitcode ("rlc", "a");
6009 if (sameRegs (AOP (left), AOP (result)) &&
6010 size >= MSB32 + offr && offr != LSB)
6011 emitcode ("xch", "a,%s",
6012 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6014 aopPut (AOP (result), "a", MSB24 + offr);
6017 if (size > MSB32 + offr)
6019 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6021 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6024 emitcode ("rlc", "a");
6025 aopPut (AOP (result), "a", MSB32 + offr);
6028 aopPut (AOP (result), zero, LSB);
6031 /*-----------------------------------------------------------------*/
6032 /* genlshFour - shift four byte by a known amount != 0 */
6033 /*-----------------------------------------------------------------*/
6035 genlshFour (operand * result, operand * left, int shCount)
6039 size = AOP_SIZE (result);
6041 /* if shifting more that 3 bytes */
6046 /* lowest order of left goes to the highest
6047 order of the destination */
6048 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6050 movLeft2Result (left, LSB, result, MSB32, 0);
6051 aopPut (AOP (result), zero, LSB);
6052 aopPut (AOP (result), zero, MSB16);
6053 aopPut (AOP (result), zero, MSB24);
6057 /* more than two bytes */
6058 else if (shCount >= 16)
6060 /* lower order two bytes goes to higher order two bytes */
6062 /* if some more remaining */
6064 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6067 movLeft2Result (left, MSB16, result, MSB32, 0);
6068 movLeft2Result (left, LSB, result, MSB24, 0);
6070 aopPut (AOP (result), zero, MSB16);
6071 aopPut (AOP (result), zero, LSB);
6075 /* if more than 1 byte */
6076 else if (shCount >= 8)
6078 /* lower order three bytes goes to higher order three bytes */
6083 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6085 movLeft2Result (left, LSB, result, MSB16, 0);
6091 movLeft2Result (left, MSB24, result, MSB32, 0);
6092 movLeft2Result (left, MSB16, result, MSB24, 0);
6093 movLeft2Result (left, LSB, result, MSB16, 0);
6094 aopPut (AOP (result), zero, LSB);
6096 else if (shCount == 1)
6097 shiftLLong (left, result, MSB16);
6100 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6101 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6102 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6103 aopPut (AOP (result), zero, LSB);
6108 /* 1 <= shCount <= 7 */
6109 else if (shCount <= 2)
6111 shiftLLong (left, result, LSB);
6113 shiftLLong (result, result, LSB);
6115 /* 3 <= shCount <= 7, optimize */
6118 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6119 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6120 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6124 /*-----------------------------------------------------------------*/
6125 /* genLeftShiftLiteral - left shifting by known count */
6126 /*-----------------------------------------------------------------*/
6128 genLeftShiftLiteral (operand * left,
6133 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6136 freeAsmop (right, NULL, ic, TRUE);
6138 aopOp (left, ic, FALSE);
6139 aopOp (result, ic, FALSE);
6141 size = getSize (operandType (result));
6144 emitcode ("; shift left ", "result %d, left %d", size,
6148 /* I suppose that the left size >= result size */
6153 movLeft2Result (left, size, result, size, 0);
6157 else if (shCount >= (size * 8))
6159 aopPut (AOP (result), zero, size);
6165 genlshOne (result, left, shCount);
6169 genlshTwo (result, left, shCount);
6173 genlshFour (result, left, shCount);
6176 fprintf(stderr, "*** ack! mystery literal shift!\n");
6180 freeAsmop (left, NULL, ic, TRUE);
6181 freeAsmop (result, NULL, ic, TRUE);
6184 /*-----------------------------------------------------------------*/
6185 /* genLeftShift - generates code for left shifting */
6186 /*-----------------------------------------------------------------*/
6188 genLeftShift (iCode * ic)
6190 operand *left, *right, *result;
6193 symbol *tlbl, *tlbl1;
6195 right = IC_RIGHT (ic);
6196 left = IC_LEFT (ic);
6197 result = IC_RESULT (ic);
6199 aopOp (right, ic, FALSE);
6201 /* if the shift count is known then do it
6202 as efficiently as possible */
6203 if (AOP_TYPE (right) == AOP_LIT)
6205 genLeftShiftLiteral (left, right, result, ic);
6209 /* shift count is unknown then we have to form
6210 a loop get the loop count in B : Note: we take
6211 only the lower order byte since shifting
6212 more that 32 bits make no sense anyway, ( the
6213 largest size of an object can be only 32 bits ) */
6215 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6216 emitcode ("inc", "b");
6217 freeAsmop (right, NULL, ic, TRUE);
6218 aopOp (left, ic, FALSE);
6219 aopOp (result, ic, FALSE);
6221 /* now move the left to the result if they are not the
6223 if (!sameRegs (AOP (left), AOP (result)) &&
6224 AOP_SIZE (result) > 1)
6227 size = AOP_SIZE (result);
6231 l = aopGet (AOP (left), offset, FALSE, TRUE);
6232 if (*l == '@' && (IS_AOP_PREG (result)))
6235 emitcode ("mov", "a,%s", l);
6236 aopPut (AOP (result), "a", offset);
6239 aopPut (AOP (result), l, offset);
6244 tlbl = newiTempLabel (NULL);
6245 size = AOP_SIZE (result);
6247 tlbl1 = newiTempLabel (NULL);
6249 /* if it is only one byte then */
6252 symbol *tlbl1 = newiTempLabel (NULL);
6254 l = aopGet (AOP (left), 0, FALSE, FALSE);
6256 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6257 emitcode ("", "%05d$:", tlbl->key + 100);
6258 emitcode ("add", "a,acc");
6259 emitcode ("", "%05d$:", tlbl1->key + 100);
6260 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6261 aopPut (AOP (result), "a", 0);
6265 reAdjustPreg (AOP (result));
6267 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6268 emitcode ("", "%05d$:", tlbl->key + 100);
6269 l = aopGet (AOP (result), offset, FALSE, FALSE);
6271 emitcode ("add", "a,acc");
6272 aopPut (AOP (result), "a", offset++);
6275 l = aopGet (AOP (result), offset, FALSE, FALSE);
6277 emitcode ("rlc", "a");
6278 aopPut (AOP (result), "a", offset++);
6280 reAdjustPreg (AOP (result));
6282 emitcode ("", "%05d$:", tlbl1->key + 100);
6283 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6285 freeAsmop (left, NULL, ic, TRUE);
6286 freeAsmop (result, NULL, ic, TRUE);
6289 /*-----------------------------------------------------------------*/
6290 /* genrshOne - right shift a one byte quantity by known count */
6291 /*-----------------------------------------------------------------*/
6293 genrshOne (operand * result, operand * left,
6294 int shCount, int sign)
6296 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6299 /*-----------------------------------------------------------------*/
6300 /* genrshTwo - right shift two bytes by known amount != 0 */
6301 /*-----------------------------------------------------------------*/
6303 genrshTwo (operand * result, operand * left,
6304 int shCount, int sign)
6306 /* if shCount >= 8 */
6311 shiftR1Left2Result (left, MSB16, result, LSB,
6314 movLeft2Result (left, MSB16, result, LSB, sign);
6315 addSign (result, MSB16, sign);
6318 /* 1 <= shCount <= 7 */
6320 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6323 /*-----------------------------------------------------------------*/
6324 /* shiftRLong - shift right one long from left to result */
6325 /* offl = LSB or MSB16 */
6326 /*-----------------------------------------------------------------*/
6328 shiftRLong (operand * left, int offl,
6329 operand * result, int sign)
6331 int isSameRegs=sameRegs(AOP(left),AOP(result));
6333 if (isSameRegs && offl>1) {
6334 // we are in big trouble, but this shouldn't happen
6335 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6338 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6343 emitcode ("rlc", "a");
6344 emitcode ("subb", "a,acc");
6345 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6347 aopPut (AOP(result), zero, MSB32);
6352 emitcode ("clr", "c");
6354 emitcode ("mov", "c,acc.7");
6357 emitcode ("rrc", "a");
6359 if (isSameRegs && offl==MSB16) {
6360 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6362 aopPut (AOP (result), "a", MSB32);
6363 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6366 emitcode ("rrc", "a");
6367 if (isSameRegs && offl==1) {
6368 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6370 aopPut (AOP (result), "a", MSB24);
6371 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6373 emitcode ("rrc", "a");
6374 aopPut (AOP (result), "a", MSB16 - offl);
6378 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6379 emitcode ("rrc", "a");
6380 aopPut (AOP (result), "a", LSB);
6384 /*-----------------------------------------------------------------*/
6385 /* genrshFour - shift four byte by a known amount != 0 */
6386 /*-----------------------------------------------------------------*/
6388 genrshFour (operand * result, operand * left,
6389 int shCount, int sign)
6391 /* if shifting more that 3 bytes */
6396 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6398 movLeft2Result (left, MSB32, result, LSB, sign);
6399 addSign (result, MSB16, sign);
6401 else if (shCount >= 16)
6405 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6408 movLeft2Result (left, MSB24, result, LSB, 0);
6409 movLeft2Result (left, MSB32, result, MSB16, sign);
6411 addSign (result, MSB24, sign);
6413 else if (shCount >= 8)
6417 shiftRLong (left, MSB16, result, sign);
6418 else if (shCount == 0)
6420 movLeft2Result (left, MSB16, result, LSB, 0);
6421 movLeft2Result (left, MSB24, result, MSB16, 0);
6422 movLeft2Result (left, MSB32, result, MSB24, sign);
6423 addSign (result, MSB32, sign);
6427 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6428 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6429 /* the last shift is signed */
6430 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6431 addSign (result, MSB32, sign);
6435 { /* 1 <= shCount <= 7 */
6438 shiftRLong (left, LSB, result, sign);
6440 shiftRLong (result, LSB, result, sign);
6444 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6445 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6446 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6451 /*-----------------------------------------------------------------*/
6452 /* genRightShiftLiteral - right shifting by known count */
6453 /*-----------------------------------------------------------------*/
6455 genRightShiftLiteral (operand * left,
6461 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6464 freeAsmop (right, NULL, ic, TRUE);
6466 aopOp (left, ic, FALSE);
6467 aopOp (result, ic, FALSE);
6470 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6474 size = getDataSize (left);
6475 /* test the LEFT size !!! */
6477 /* I suppose that the left size >= result size */
6480 size = getDataSize (result);
6482 movLeft2Result (left, size, result, size, 0);
6485 else if (shCount >= (size * 8))
6488 /* get sign in acc.7 */
6489 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6490 addSign (result, LSB, sign);
6497 genrshOne (result, left, shCount, sign);
6501 genrshTwo (result, left, shCount, sign);
6505 genrshFour (result, left, shCount, sign);
6511 freeAsmop (left, NULL, ic, TRUE);
6512 freeAsmop (result, NULL, ic, TRUE);
6516 /*-----------------------------------------------------------------*/
6517 /* genSignedRightShift - right shift of signed number */
6518 /*-----------------------------------------------------------------*/
6520 genSignedRightShift (iCode * ic)
6522 operand *right, *left, *result;
6525 symbol *tlbl, *tlbl1;
6527 /* we do it the hard way put the shift count in b
6528 and loop thru preserving the sign */
6530 right = IC_RIGHT (ic);
6531 left = IC_LEFT (ic);
6532 result = IC_RESULT (ic);
6534 aopOp (right, ic, FALSE);
6537 if (AOP_TYPE (right) == AOP_LIT)
6539 genRightShiftLiteral (left, right, result, ic, 1);
6542 /* shift count is unknown then we have to form
6543 a loop get the loop count in B : Note: we take
6544 only the lower order byte since shifting
6545 more that 32 bits make no sense anyway, ( the
6546 largest size of an object can be only 32 bits ) */
6548 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6549 emitcode ("inc", "b");
6550 freeAsmop (right, NULL, ic, TRUE);
6551 aopOp (left, ic, FALSE);
6552 aopOp (result, ic, FALSE);
6554 /* now move the left to the result if they are not the
6556 if (!sameRegs (AOP (left), AOP (result)) &&
6557 AOP_SIZE (result) > 1)
6560 size = AOP_SIZE (result);
6564 l = aopGet (AOP (left), offset, FALSE, TRUE);
6565 if (*l == '@' && IS_AOP_PREG (result))
6568 emitcode ("mov", "a,%s", l);
6569 aopPut (AOP (result), "a", offset);
6572 aopPut (AOP (result), l, offset);
6577 /* mov the highest order bit to OVR */
6578 tlbl = newiTempLabel (NULL);
6579 tlbl1 = newiTempLabel (NULL);
6581 size = AOP_SIZE (result);
6583 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6584 emitcode ("rlc", "a");
6585 emitcode ("mov", "ov,c");
6586 /* if it is only one byte then */
6589 l = aopGet (AOP (left), 0, FALSE, FALSE);
6591 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6592 emitcode ("", "%05d$:", tlbl->key + 100);
6593 emitcode ("mov", "c,ov");
6594 emitcode ("rrc", "a");
6595 emitcode ("", "%05d$:", tlbl1->key + 100);
6596 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6597 aopPut (AOP (result), "a", 0);
6601 reAdjustPreg (AOP (result));
6602 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6603 emitcode ("", "%05d$:", tlbl->key + 100);
6604 emitcode ("mov", "c,ov");
6607 l = aopGet (AOP (result), offset, FALSE, FALSE);
6609 emitcode ("rrc", "a");
6610 aopPut (AOP (result), "a", offset--);
6612 reAdjustPreg (AOP (result));
6613 emitcode ("", "%05d$:", tlbl1->key + 100);
6614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6617 freeAsmop (left, NULL, ic, TRUE);
6618 freeAsmop (result, NULL, ic, TRUE);
6621 /*-----------------------------------------------------------------*/
6622 /* genRightShift - generate code for right shifting */
6623 /*-----------------------------------------------------------------*/
6625 genRightShift (iCode * ic)
6627 operand *right, *left, *result;
6631 symbol *tlbl, *tlbl1;
6633 /* if signed then we do it the hard way preserve the
6634 sign bit moving it inwards */
6635 retype = getSpec (operandType (IC_RESULT (ic)));
6637 if (!SPEC_USIGN (retype))
6639 genSignedRightShift (ic);
6643 /* signed & unsigned types are treated the same : i.e. the
6644 signed is NOT propagated inwards : quoting from the
6645 ANSI - standard : "for E1 >> E2, is equivalent to division
6646 by 2**E2 if unsigned or if it has a non-negative value,
6647 otherwise the result is implementation defined ", MY definition
6648 is that the sign does not get propagated */
6650 right = IC_RIGHT (ic);
6651 left = IC_LEFT (ic);
6652 result = IC_RESULT (ic);
6654 aopOp (right, ic, FALSE);
6656 /* if the shift count is known then do it
6657 as efficiently as possible */
6658 if (AOP_TYPE (right) == AOP_LIT)
6660 genRightShiftLiteral (left, right, result, ic, 0);
6664 /* shift count is unknown then we have to form
6665 a loop get the loop count in B : Note: we take
6666 only the lower order byte since shifting
6667 more that 32 bits make no sense anyway, ( the
6668 largest size of an object can be only 32 bits ) */
6670 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6671 emitcode ("inc", "b");
6672 freeAsmop (right, NULL, ic, TRUE);
6673 aopOp (left, ic, FALSE);
6674 aopOp (result, ic, FALSE);
6676 /* now move the left to the result if they are not the
6678 if (!sameRegs (AOP (left), AOP (result)) &&
6679 AOP_SIZE (result) > 1)
6682 size = AOP_SIZE (result);
6686 l = aopGet (AOP (left), offset, FALSE, TRUE);
6687 if (*l == '@' && IS_AOP_PREG (result))
6690 emitcode ("mov", "a,%s", l);
6691 aopPut (AOP (result), "a", offset);
6694 aopPut (AOP (result), l, offset);
6699 tlbl = newiTempLabel (NULL);
6700 tlbl1 = newiTempLabel (NULL);
6701 size = AOP_SIZE (result);
6704 /* if it is only one byte then */
6707 l = aopGet (AOP (left), 0, FALSE, FALSE);
6709 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6710 emitcode ("", "%05d$:", tlbl->key + 100);
6712 emitcode ("rrc", "a");
6713 emitcode ("", "%05d$:", tlbl1->key + 100);
6714 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6715 aopPut (AOP (result), "a", 0);
6719 reAdjustPreg (AOP (result));
6720 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6721 emitcode ("", "%05d$:", tlbl->key + 100);
6725 l = aopGet (AOP (result), offset, FALSE, FALSE);
6727 emitcode ("rrc", "a");
6728 aopPut (AOP (result), "a", offset--);
6730 reAdjustPreg (AOP (result));
6732 emitcode ("", "%05d$:", tlbl1->key + 100);
6733 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6736 freeAsmop (left, NULL, ic, TRUE);
6737 freeAsmop (result, NULL, ic, TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genUnpackBits - generates code for unpacking bits */
6742 /*-----------------------------------------------------------------*/
6744 genUnpackBits (operand * result, char *rname, int ptype)
6752 etype = getSpec (operandType (result));
6753 rsize = getSize (operandType (result));
6754 /* read the first byte */
6760 emitcode ("mov", "a,@%s", rname);
6764 emitcode ("movx", "a,@%s", rname);
6768 emitcode ("movx", "a,@dptr");
6772 emitcode ("clr", "a");
6773 emitcode ("movc", "a,%s", "@a+dptr");
6777 emitcode ("lcall", "__gptrget");
6781 rlen = SPEC_BLEN (etype);
6783 /* if we have bitdisplacement then it fits */
6784 /* into this byte completely or if length is */
6785 /* less than a byte */
6786 if ((shCnt = SPEC_BSTR (etype)) ||
6787 (SPEC_BLEN (etype) <= 8))
6790 /* shift right acc */
6793 emitcode ("anl", "a,#0x%02x",
6794 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6795 aopPut (AOP (result), "a", offset++);
6799 /* bit field did not fit in a byte */
6800 aopPut (AOP (result), "a", offset++);
6809 emitcode ("inc", "%s", rname);
6810 emitcode ("mov", "a,@%s", rname);
6814 emitcode ("inc", "%s", rname);
6815 emitcode ("movx", "a,@%s", rname);
6819 emitcode ("inc", "dptr");
6820 emitcode ("movx", "a,@dptr");
6824 emitcode ("clr", "a");
6825 emitcode ("inc", "dptr");
6826 emitcode ("movc", "a", "@a+dptr");
6830 emitcode ("inc", "dptr");
6831 emitcode ("lcall", "__gptrget");
6836 /* if we are done */
6840 aopPut (AOP (result), "a", offset++);
6846 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6848 aopPut (AOP (result), "a", offset++);
6856 aopPut (AOP (result), zero, offset++);
6862 /*-----------------------------------------------------------------*/
6863 /* genDataPointerGet - generates code when ptr offset is known */
6864 /*-----------------------------------------------------------------*/
6866 genDataPointerGet (operand * left,
6872 int size, offset = 0;
6873 aopOp (result, ic, TRUE);
6875 /* get the string representation of the name */
6876 l = aopGet (AOP (left), 0, FALSE, TRUE);
6877 size = AOP_SIZE (result);
6881 sprintf (buffer, "(%s + %d)", l + 1, offset);
6883 sprintf (buffer, "%s", l + 1);
6884 aopPut (AOP (result), buffer, offset++);
6887 freeAsmop (left, NULL, ic, TRUE);
6888 freeAsmop (result, NULL, ic, TRUE);
6891 /*-----------------------------------------------------------------*/
6892 /* genNearPointerGet - emitcode for near pointer fetch */
6893 /*-----------------------------------------------------------------*/
6895 genNearPointerGet (operand * left,
6903 sym_link *rtype, *retype;
6904 sym_link *ltype = operandType (left);
6907 rtype = operandType (result);
6908 retype = getSpec (rtype);
6910 aopOp (left, ic, FALSE);
6912 /* if left is rematerialisable and
6913 result is not bit variable type and
6914 the left is pointer to data space i.e
6915 lower 128 bytes of space */
6916 if (AOP_TYPE (left) == AOP_IMMD &&
6917 !IS_BITVAR (retype) &&
6918 DCL_TYPE (ltype) == POINTER)
6920 genDataPointerGet (left, result, ic);
6924 /* if the value is already in a pointer register
6925 then don't need anything more */
6926 if (!AOP_INPREG (AOP (left)))
6928 /* otherwise get a free pointer register */
6930 preg = getFreePtr (ic, &aop, FALSE);
6931 emitcode ("mov", "%s,%s",
6933 aopGet (AOP (left), 0, FALSE, TRUE));
6937 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6939 aopOp (result, ic, FALSE);
6941 /* if bitfield then unpack the bits */
6942 if (IS_BITVAR (retype))
6943 genUnpackBits (result, rname, POINTER);
6946 /* we have can just get the values */
6947 int size = AOP_SIZE (result);
6952 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6955 emitcode ("mov", "a,@%s", rname);
6956 aopPut (AOP (result), "a", offset);
6960 sprintf (buffer, "@%s", rname);
6961 aopPut (AOP (result), buffer, offset);
6965 emitcode ("inc", "%s", rname);
6969 /* now some housekeeping stuff */
6970 if (aop) /* we had to allocate for this iCode */
6972 if (pi) { /* post increment present */
6973 aopPut(AOP ( left ),rname,0);
6975 freeAsmop (NULL, aop, ic, TRUE);
6979 /* we did not allocate which means left
6980 already in a pointer register, then
6981 if size > 0 && this could be used again
6982 we have to point it back to where it
6984 if ((AOP_SIZE (result) > 1 &&
6985 !OP_SYMBOL (left)->remat &&
6986 (OP_SYMBOL (left)->liveTo > ic->seq ||
6990 int size = AOP_SIZE (result) - 1;
6992 emitcode ("dec", "%s", rname);
6997 freeAsmop (left, NULL, ic, TRUE);
6998 freeAsmop (result, NULL, ic, TRUE);
6999 if (pi) pi->generated = 1;
7002 /*-----------------------------------------------------------------*/
7003 /* genPagedPointerGet - emitcode for paged pointer fetch */
7004 /*-----------------------------------------------------------------*/
7006 genPagedPointerGet (operand * left,
7014 sym_link *rtype, *retype;
7016 rtype = operandType (result);
7017 retype = getSpec (rtype);
7019 aopOp (left, ic, FALSE);
7021 /* if the value is already in a pointer register
7022 then don't need anything more */
7023 if (!AOP_INPREG (AOP (left)))
7025 /* otherwise get a free pointer register */
7027 preg = getFreePtr (ic, &aop, FALSE);
7028 emitcode ("mov", "%s,%s",
7030 aopGet (AOP (left), 0, FALSE, TRUE));
7034 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7036 aopOp (result, ic, FALSE);
7038 /* if bitfield then unpack the bits */
7039 if (IS_BITVAR (retype))
7040 genUnpackBits (result, rname, PPOINTER);
7043 /* we have can just get the values */
7044 int size = AOP_SIZE (result);
7050 emitcode ("movx", "a,@%s", rname);
7051 aopPut (AOP (result), "a", offset);
7056 emitcode ("inc", "%s", rname);
7060 /* now some housekeeping stuff */
7061 if (aop) /* we had to allocate for this iCode */
7063 if (pi) aopPut ( AOP (left), rname, 0);
7064 freeAsmop (NULL, aop, ic, TRUE);
7068 /* we did not allocate which means left
7069 already in a pointer register, then
7070 if size > 0 && this could be used again
7071 we have to point it back to where it
7073 if ((AOP_SIZE (result) > 1 &&
7074 !OP_SYMBOL (left)->remat &&
7075 (OP_SYMBOL (left)->liveTo > ic->seq ||
7079 int size = AOP_SIZE (result) - 1;
7081 emitcode ("dec", "%s", rname);
7086 freeAsmop (left, NULL, ic, TRUE);
7087 freeAsmop (result, NULL, ic, TRUE);
7088 if (pi) pi->generated = 1;
7092 /*-----------------------------------------------------------------*/
7093 /* genFarPointerGet - gget value from far space */
7094 /*-----------------------------------------------------------------*/
7096 genFarPointerGet (operand * left,
7097 operand * result, iCode * ic, iCode * pi)
7100 sym_link *retype = getSpec (operandType (result));
7102 aopOp (left, ic, FALSE);
7104 /* if the operand is already in dptr
7105 then we do nothing else we move the value to dptr */
7106 if (AOP_TYPE (left) != AOP_STR)
7108 /* if this is remateriazable */
7109 if (AOP_TYPE (left) == AOP_IMMD)
7110 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7112 { /* we need to get it byte by byte */
7113 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7114 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7117 /* so dptr know contains the address */
7118 aopOp (result, ic, FALSE);
7120 /* if bit then unpack */
7121 if (IS_BITVAR (retype))
7122 genUnpackBits (result, "dptr", FPOINTER);
7125 size = AOP_SIZE (result);
7130 emitcode ("movx", "a,@dptr");
7131 aopPut (AOP (result), "a", offset++);
7133 emitcode ("inc", "dptr");
7137 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7138 aopPut ( AOP (left), "dpl", 0);
7139 aopPut ( AOP (left), "dph", 1);
7142 freeAsmop (left, NULL, ic, TRUE);
7143 freeAsmop (result, NULL, ic, TRUE);
7146 /*-----------------------------------------------------------------*/
7147 /* genCodePointerGet - gget value from code space */
7148 /*-----------------------------------------------------------------*/
7150 genCodePointerGet (operand * left,
7151 operand * result, iCode * ic, iCode *pi)
7154 sym_link *retype = getSpec (operandType (result));
7156 aopOp (left, ic, FALSE);
7158 /* if the operand is already in dptr
7159 then we do nothing else we move the value to dptr */
7160 if (AOP_TYPE (left) != AOP_STR)
7162 /* if this is remateriazable */
7163 if (AOP_TYPE (left) == AOP_IMMD)
7164 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7166 { /* we need to get it byte by byte */
7167 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7168 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7171 /* so dptr know contains the address */
7172 aopOp (result, ic, FALSE);
7174 /* if bit then unpack */
7175 if (IS_BITVAR (retype))
7176 genUnpackBits (result, "dptr", CPOINTER);
7179 size = AOP_SIZE (result);
7184 emitcode ("clr", "a");
7185 emitcode ("movc", "a,@a+dptr");
7186 aopPut (AOP (result), "a", offset++);
7188 emitcode ("inc", "dptr");
7192 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7193 aopPut ( AOP (left), "dpl", 0);
7194 aopPut ( AOP (left), "dph", 1);
7197 freeAsmop (left, NULL, ic, TRUE);
7198 freeAsmop (result, NULL, ic, TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* genGenPointerGet - gget value from generic pointer space */
7203 /*-----------------------------------------------------------------*/
7205 genGenPointerGet (operand * left,
7206 operand * result, iCode * ic, iCode *pi)
7209 sym_link *retype = getSpec (operandType (result));
7211 aopOp (left, ic, FALSE);
7213 /* if the operand is already in dptr
7214 then we do nothing else we move the value to dptr */
7215 if (AOP_TYPE (left) != AOP_STR)
7217 /* if this is remateriazable */
7218 if (AOP_TYPE (left) == AOP_IMMD)
7220 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7221 emitcode ("mov", "b,#%d", pointerCode (retype));
7224 { /* we need to get it byte by byte */
7225 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7226 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7227 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7230 /* so dptr know contains the address */
7231 aopOp (result, ic, FALSE);
7233 /* if bit then unpack */
7234 if (IS_BITVAR (retype))
7235 genUnpackBits (result, "dptr", GPOINTER);
7238 size = AOP_SIZE (result);
7243 emitcode ("lcall", "__gptrget");
7244 aopPut (AOP (result), "a", offset++);
7246 emitcode ("inc", "dptr");
7250 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7251 aopPut ( AOP (left), "dpl", 0);
7252 aopPut ( AOP (left), "dph", 1);
7255 freeAsmop (left, NULL, ic, TRUE);
7256 freeAsmop (result, NULL, ic, TRUE);
7259 /*-----------------------------------------------------------------*/
7260 /* genPointerGet - generate code for pointer get */
7261 /*-----------------------------------------------------------------*/
7263 genPointerGet (iCode * ic, iCode *pi)
7265 operand *left, *result;
7266 sym_link *type, *etype;
7269 left = IC_LEFT (ic);
7270 result = IC_RESULT (ic);
7272 /* depending on the type of pointer we need to
7273 move it to the correct pointer register */
7274 type = operandType (left);
7275 etype = getSpec (type);
7276 /* if left is of type of pointer then it is simple */
7277 if (IS_PTR (type) && !IS_FUNC (type->next))
7278 p_type = DCL_TYPE (type);
7281 /* we have to go by the storage class */
7282 p_type = PTR_TYPE (SPEC_OCLS (etype));
7285 /* now that we have the pointer type we assign
7286 the pointer values */
7292 genNearPointerGet (left, result, ic, pi);
7296 genPagedPointerGet (left, result, ic, pi);
7300 genFarPointerGet (left, result, ic, pi);
7304 genCodePointerGet (left, result, ic, pi);
7308 genGenPointerGet (left, result, ic, pi);
7314 /*-----------------------------------------------------------------*/
7315 /* genPackBits - generates code for packed bit storage */
7316 /*-----------------------------------------------------------------*/
7318 genPackBits (sym_link * etype,
7320 char *rname, int p_type)
7328 blen = SPEC_BLEN (etype);
7329 bstr = SPEC_BSTR (etype);
7331 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7334 /* if the bit lenth is less than or */
7335 /* it exactly fits a byte then */
7336 if (SPEC_BLEN (etype) <= 8)
7338 shCount = SPEC_BSTR (etype);
7340 /* shift left acc */
7343 if (SPEC_BLEN (etype) < 8)
7344 { /* if smaller than a byte */
7350 emitcode ("mov", "b,a");
7351 emitcode ("mov", "a,@%s", rname);
7355 emitcode ("mov", "b,a");
7356 emitcode ("movx", "a,@dptr");
7360 emitcode ("push", "b");
7361 emitcode ("push", "acc");
7362 emitcode ("lcall", "__gptrget");
7363 emitcode ("pop", "b");
7367 emitcode ("anl", "a,#0x%02x", (unsigned char)
7368 ((unsigned char) (0xFF << (blen + bstr)) |
7369 (unsigned char) (0xFF >> (8 - bstr))));
7370 emitcode ("orl", "a,b");
7371 if (p_type == GPOINTER)
7372 emitcode ("pop", "b");
7379 emitcode ("mov", "@%s,a", rname);
7383 emitcode ("movx", "@dptr,a");
7387 emitcode ("lcall", "__gptrput");
7392 if (SPEC_BLEN (etype) <= 8)
7395 emitcode ("inc", "%s", rname);
7396 rLen = SPEC_BLEN (etype);
7398 /* now generate for lengths greater than one byte */
7402 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7414 emitcode ("mov", "@%s,a", rname);
7417 emitcode ("mov", "@%s,%s", rname, l);
7422 emitcode ("movx", "@dptr,a");
7427 emitcode ("lcall", "__gptrput");
7430 emitcode ("inc", "%s", rname);
7435 /* last last was not complete */
7438 /* save the byte & read byte */
7442 emitcode ("mov", "b,a");
7443 emitcode ("mov", "a,@%s", rname);
7447 emitcode ("mov", "b,a");
7448 emitcode ("movx", "a,@dptr");
7452 emitcode ("push", "b");
7453 emitcode ("push", "acc");
7454 emitcode ("lcall", "__gptrget");
7455 emitcode ("pop", "b");
7459 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7460 emitcode ("orl", "a,b");
7463 if (p_type == GPOINTER)
7464 emitcode ("pop", "b");
7470 emitcode ("mov", "@%s,a", rname);
7474 emitcode ("movx", "@dptr,a");
7478 emitcode ("lcall", "__gptrput");
7482 /*-----------------------------------------------------------------*/
7483 /* genDataPointerSet - remat pointer to data space */
7484 /*-----------------------------------------------------------------*/
7486 genDataPointerSet (operand * right,
7490 int size, offset = 0;
7491 char *l, buffer[256];
7493 aopOp (right, ic, FALSE);
7495 l = aopGet (AOP (result), 0, FALSE, TRUE);
7496 size = AOP_SIZE (right);
7500 sprintf (buffer, "(%s + %d)", l + 1, offset);
7502 sprintf (buffer, "%s", l + 1);
7503 emitcode ("mov", "%s,%s", buffer,
7504 aopGet (AOP (right), offset++, FALSE, FALSE));
7507 freeAsmop (right, NULL, ic, TRUE);
7508 freeAsmop (result, NULL, ic, TRUE);
7511 /*-----------------------------------------------------------------*/
7512 /* genNearPointerSet - emitcode for near pointer put */
7513 /*-----------------------------------------------------------------*/
7515 genNearPointerSet (operand * right,
7523 sym_link *retype, *letype;
7524 sym_link *ptype = operandType (result);
7526 retype = getSpec (operandType (right));
7527 letype = getSpec (ptype);
7528 aopOp (result, ic, FALSE);
7530 /* if the result is rematerializable &
7531 in data space & not a bit variable */
7532 if (AOP_TYPE (result) == AOP_IMMD &&
7533 DCL_TYPE (ptype) == POINTER &&
7534 !IS_BITVAR (retype) &&
7535 !IS_BITVAR (letype))
7537 genDataPointerSet (right, result, ic);
7541 /* if the value is already in a pointer register
7542 then don't need anything more */
7543 if (!AOP_INPREG (AOP (result)))
7545 /* otherwise get a free pointer register */
7547 preg = getFreePtr (ic, &aop, FALSE);
7548 emitcode ("mov", "%s,%s",
7550 aopGet (AOP (result), 0, FALSE, TRUE));
7554 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7556 aopOp (right, ic, FALSE);
7558 /* if bitfield then unpack the bits */
7559 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7560 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7563 /* we have can just get the values */
7564 int size = AOP_SIZE (right);
7569 l = aopGet (AOP (right), offset, FALSE, TRUE);
7573 emitcode ("mov", "@%s,a", rname);
7576 emitcode ("mov", "@%s,%s", rname, l);
7578 emitcode ("inc", "%s", rname);
7583 /* now some housekeeping stuff */
7584 if (aop) /* we had to allocate for this iCode */
7586 if (pi) aopPut (AOP (result),rname,0);
7587 freeAsmop (NULL, aop, ic, TRUE);
7591 /* we did not allocate which means left
7592 already in a pointer register, then
7593 if size > 0 && this could be used again
7594 we have to point it back to where it
7596 if ((AOP_SIZE (right) > 1 &&
7597 !OP_SYMBOL (result)->remat &&
7598 (OP_SYMBOL (result)->liveTo > ic->seq ||
7602 int size = AOP_SIZE (right) - 1;
7604 emitcode ("dec", "%s", rname);
7609 if (pi) pi->generated = 1;
7610 freeAsmop (result, NULL, ic, TRUE);
7611 freeAsmop (right, NULL, ic, TRUE);
7614 /*-----------------------------------------------------------------*/
7615 /* genPagedPointerSet - emitcode for Paged pointer put */
7616 /*-----------------------------------------------------------------*/
7618 genPagedPointerSet (operand * right,
7626 sym_link *retype, *letype;
7628 retype = getSpec (operandType (right));
7629 letype = getSpec (operandType (result));
7631 aopOp (result, ic, FALSE);
7633 /* if the value is already in a pointer register
7634 then don't need anything more */
7635 if (!AOP_INPREG (AOP (result)))
7637 /* otherwise get a free pointer register */
7639 preg = getFreePtr (ic, &aop, FALSE);
7640 emitcode ("mov", "%s,%s",
7642 aopGet (AOP (result), 0, FALSE, TRUE));
7646 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7648 aopOp (right, ic, FALSE);
7650 /* if bitfield then unpack the bits */
7651 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7652 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7655 /* we have can just get the values */
7656 int size = AOP_SIZE (right);
7661 l = aopGet (AOP (right), offset, FALSE, TRUE);
7664 emitcode ("movx", "@%s,a", rname);
7667 emitcode ("inc", "%s", rname);
7673 /* now some housekeeping stuff */
7674 if (aop) /* we had to allocate for this iCode */
7676 if (pi) aopPut (AOP (result),rname,0);
7677 freeAsmop (NULL, aop, ic, TRUE);
7681 /* we did not allocate which means left
7682 already in a pointer register, then
7683 if size > 0 && this could be used again
7684 we have to point it back to where it
7686 if (AOP_SIZE (right) > 1 &&
7687 !OP_SYMBOL (result)->remat &&
7688 (OP_SYMBOL (result)->liveTo > ic->seq ||
7691 int size = AOP_SIZE (right) - 1;
7693 emitcode ("dec", "%s", rname);
7698 if (pi) pi->generated = 1;
7699 freeAsmop (result, NULL, ic, TRUE);
7700 freeAsmop (right, NULL, ic, TRUE);
7705 /*-----------------------------------------------------------------*/
7706 /* genFarPointerSet - set value from far space */
7707 /*-----------------------------------------------------------------*/
7709 genFarPointerSet (operand * right,
7710 operand * result, iCode * ic, iCode * pi)
7713 sym_link *retype = getSpec (operandType (right));
7714 sym_link *letype = getSpec (operandType (result));
7715 aopOp (result, ic, FALSE);
7717 /* if the operand is already in dptr
7718 then we do nothing else we move the value to dptr */
7719 if (AOP_TYPE (result) != AOP_STR)
7721 /* if this is remateriazable */
7722 if (AOP_TYPE (result) == AOP_IMMD)
7723 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7725 { /* we need to get it byte by byte */
7726 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7727 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7730 /* so dptr know contains the address */
7731 aopOp (right, ic, FALSE);
7733 /* if bit then unpack */
7734 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7735 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7738 size = AOP_SIZE (right);
7743 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7745 emitcode ("movx", "@dptr,a");
7747 emitcode ("inc", "dptr");
7750 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7751 aopPut (AOP(result),"dpl",0);
7752 aopPut (AOP(result),"dph",1);
7755 freeAsmop (result, NULL, ic, TRUE);
7756 freeAsmop (right, NULL, ic, TRUE);
7759 /*-----------------------------------------------------------------*/
7760 /* genGenPointerSet - set value from generic pointer space */
7761 /*-----------------------------------------------------------------*/
7763 genGenPointerSet (operand * right,
7764 operand * result, iCode * ic, iCode * pi)
7767 sym_link *retype = getSpec (operandType (right));
7768 sym_link *letype = getSpec (operandType (result));
7770 aopOp (result, ic, FALSE);
7772 /* if the operand is already in dptr
7773 then we do nothing else we move the value to dptr */
7774 if (AOP_TYPE (result) != AOP_STR)
7776 /* if this is remateriazable */
7777 if (AOP_TYPE (result) == AOP_IMMD)
7779 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7780 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7783 { /* we need to get it byte by byte */
7784 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7785 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7786 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7789 /* so dptr know contains the address */
7790 aopOp (right, ic, FALSE);
7792 /* if bit then unpack */
7793 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7794 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7797 size = AOP_SIZE (right);
7802 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7804 emitcode ("lcall", "__gptrput");
7806 emitcode ("inc", "dptr");
7810 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7811 aopPut (AOP(result),"dpl",0);
7812 aopPut (AOP(result),"dph",1);
7815 freeAsmop (result, NULL, ic, TRUE);
7816 freeAsmop (right, NULL, ic, TRUE);
7819 /*-----------------------------------------------------------------*/
7820 /* genPointerSet - stores the value into a pointer location */
7821 /*-----------------------------------------------------------------*/
7823 genPointerSet (iCode * ic, iCode *pi)
7825 operand *right, *result;
7826 sym_link *type, *etype;
7829 right = IC_RIGHT (ic);
7830 result = IC_RESULT (ic);
7832 /* depending on the type of pointer we need to
7833 move it to the correct pointer register */
7834 type = operandType (result);
7835 etype = getSpec (type);
7836 /* if left is of type of pointer then it is simple */
7837 if (IS_PTR (type) && !IS_FUNC (type->next))
7839 p_type = DCL_TYPE (type);
7843 /* we have to go by the storage class */
7844 p_type = PTR_TYPE (SPEC_OCLS (etype));
7847 /* now that we have the pointer type we assign
7848 the pointer values */
7854 genNearPointerSet (right, result, ic, pi);
7858 genPagedPointerSet (right, result, ic, pi);
7862 genFarPointerSet (right, result, ic, pi);
7866 genGenPointerSet (right, result, ic, pi);
7872 /*-----------------------------------------------------------------*/
7873 /* genIfx - generate code for Ifx statement */
7874 /*-----------------------------------------------------------------*/
7876 genIfx (iCode * ic, iCode * popIc)
7878 operand *cond = IC_COND (ic);
7881 aopOp (cond, ic, FALSE);
7883 /* get the value into acc */
7884 if (AOP_TYPE (cond) != AOP_CRY)
7888 /* the result is now in the accumulator */
7889 freeAsmop (cond, NULL, ic, TRUE);
7891 /* if there was something to be popped then do it */
7895 /* if the condition is a bit variable */
7896 if (isbit && IS_ITEMP (cond) &&
7898 genIfxJump (ic, SPIL_LOC (cond)->rname);
7899 else if (isbit && !IS_ITEMP (cond))
7900 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7902 genIfxJump (ic, "a");
7907 /*-----------------------------------------------------------------*/
7908 /* genAddrOf - generates code for address of */
7909 /*-----------------------------------------------------------------*/
7911 genAddrOf (iCode * ic)
7913 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7916 aopOp (IC_RESULT (ic), ic, FALSE);
7918 /* if the operand is on the stack then we
7919 need to get the stack offset of this
7923 /* if it has an offset then we need to compute
7927 emitcode ("mov", "a,_bp");
7928 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7929 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7933 /* we can just move _bp */
7934 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7936 /* fill the result with zero */
7937 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7942 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7948 /* object not on stack then we need the name */
7949 size = AOP_SIZE (IC_RESULT (ic));
7954 char s[SDCC_NAME_MAX];
7956 sprintf (s, "#(%s >> %d)",
7960 sprintf (s, "#%s", sym->rname);
7961 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7965 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7969 /*-----------------------------------------------------------------*/
7970 /* genFarFarAssign - assignment when both are in far space */
7971 /*-----------------------------------------------------------------*/
7973 genFarFarAssign (operand * result, operand * right, iCode * ic)
7975 int size = AOP_SIZE (right);
7978 /* first push the right side on to the stack */
7981 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7983 emitcode ("push", "acc");
7986 freeAsmop (right, NULL, ic, FALSE);
7987 /* now assign DPTR to result */
7988 aopOp (result, ic, FALSE);
7989 size = AOP_SIZE (result);
7992 emitcode ("pop", "acc");
7993 aopPut (AOP (result), "a", --offset);
7995 freeAsmop (result, NULL, ic, FALSE);
7999 /*-----------------------------------------------------------------*/
8000 /* genAssign - generate code for assignment */
8001 /*-----------------------------------------------------------------*/
8003 genAssign (iCode * ic)
8005 operand *result, *right;
8007 unsigned long lit = 0L;
8009 result = IC_RESULT (ic);
8010 right = IC_RIGHT (ic);
8012 /* if they are the same */
8013 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8016 aopOp (right, ic, FALSE);
8018 /* special case both in far space */
8019 if (AOP_TYPE (right) == AOP_DPTR &&
8020 IS_TRUE_SYMOP (result) &&
8021 isOperandInFarSpace (result))
8024 genFarFarAssign (result, right, ic);
8028 aopOp (result, ic, TRUE);
8030 /* if they are the same registers */
8031 if (sameRegs (AOP (right), AOP (result)))
8034 /* if the result is a bit */
8035 if (AOP_TYPE (result) == AOP_CRY)
8038 /* if the right size is a literal then
8039 we know what the value is */
8040 if (AOP_TYPE (right) == AOP_LIT)
8042 if (((int) operandLitValue (right)))
8043 aopPut (AOP (result), one, 0);
8045 aopPut (AOP (result), zero, 0);
8049 /* the right is also a bit variable */
8050 if (AOP_TYPE (right) == AOP_CRY)
8052 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8053 aopPut (AOP (result), "c", 0);
8059 aopPut (AOP (result), "a", 0);
8063 /* bit variables done */
8065 size = AOP_SIZE (result);
8067 if (AOP_TYPE (right) == AOP_LIT)
8068 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8070 (AOP_TYPE (result) != AOP_REG) &&
8071 (AOP_TYPE (right) == AOP_LIT) &&
8072 !IS_FLOAT (operandType (right)) &&
8075 emitcode ("clr", "a");
8078 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8079 aopPut (AOP (result), "a", size);
8081 aopPut (AOP (result),
8082 aopGet (AOP (right), size, FALSE, FALSE),
8090 aopPut (AOP (result),
8091 aopGet (AOP (right), offset, FALSE, FALSE),
8098 freeAsmop (right, NULL, ic, TRUE);
8099 freeAsmop (result, NULL, ic, TRUE);
8102 /*-----------------------------------------------------------------*/
8103 /* genJumpTab - genrates code for jump table */
8104 /*-----------------------------------------------------------------*/
8106 genJumpTab (iCode * ic)
8111 aopOp (IC_JTCOND (ic), ic, FALSE);
8112 /* get the condition into accumulator */
8113 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8115 /* multiply by three */
8116 emitcode ("add", "a,acc");
8117 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8118 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8120 jtab = newiTempLabel (NULL);
8121 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8122 emitcode ("jmp", "@a+dptr");
8123 emitcode ("", "%05d$:", jtab->key + 100);
8124 /* now generate the jump labels */
8125 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8126 jtab = setNextItem (IC_JTLABELS (ic)))
8127 emitcode ("ljmp", "%05d$", jtab->key + 100);
8131 /*-----------------------------------------------------------------*/
8132 /* genCast - gen code for casting */
8133 /*-----------------------------------------------------------------*/
8135 genCast (iCode * ic)
8137 operand *result = IC_RESULT (ic);
8138 sym_link *ctype = operandType (IC_LEFT (ic));
8139 sym_link *rtype = operandType (IC_RIGHT (ic));
8140 operand *right = IC_RIGHT (ic);
8143 /* if they are equivalent then do nothing */
8144 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8147 aopOp (right, ic, FALSE);
8148 aopOp (result, ic, FALSE);
8150 /* if the result is a bit */
8151 if (AOP_TYPE (result) == AOP_CRY)
8153 /* if the right size is a literal then
8154 we know what the value is */
8155 if (AOP_TYPE (right) == AOP_LIT)
8157 if (((int) operandLitValue (right)))
8158 aopPut (AOP (result), one, 0);
8160 aopPut (AOP (result), zero, 0);
8165 /* the right is also a bit variable */
8166 if (AOP_TYPE (right) == AOP_CRY)
8168 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8169 aopPut (AOP (result), "c", 0);
8175 aopPut (AOP (result), "a", 0);
8179 /* if they are the same size : or less */
8180 if (AOP_SIZE (result) <= AOP_SIZE (right))
8183 /* if they are in the same place */
8184 if (sameRegs (AOP (right), AOP (result)))
8187 /* if they in different places then copy */
8188 size = AOP_SIZE (result);
8192 aopPut (AOP (result),
8193 aopGet (AOP (right), offset, FALSE, FALSE),
8201 /* if the result is of type pointer */
8206 sym_link *type = operandType (right);
8207 sym_link *etype = getSpec (type);
8209 /* pointer to generic pointer */
8210 if (IS_GENPTR (ctype))
8215 p_type = DCL_TYPE (type);
8218 if (SPEC_SCLS(etype)==S_REGISTER) {
8219 // let's assume it is a generic pointer
8222 /* we have to go by the storage class */
8223 p_type = PTR_TYPE (SPEC_OCLS (etype));
8227 /* the first two bytes are known */
8228 size = GPTRSIZE - 1;
8232 aopPut (AOP (result),
8233 aopGet (AOP (right), offset, FALSE, FALSE),
8237 /* the last byte depending on type */
8253 case PPOINTER: // what the fck is this?
8258 /* this should never happen */
8259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8260 "got unknown pointer type");
8263 aopPut (AOP (result), l, GPTRSIZE - 1);
8267 /* just copy the pointers */
8268 size = AOP_SIZE (result);
8272 aopPut (AOP (result),
8273 aopGet (AOP (right), offset, FALSE, FALSE),
8280 /* so we now know that the size of destination is greater
8281 than the size of the source */
8282 /* we move to result for the size of source */
8283 size = AOP_SIZE (right);
8287 aopPut (AOP (result),
8288 aopGet (AOP (right), offset, FALSE, FALSE),
8293 /* now depending on the sign of the source && destination */
8294 size = AOP_SIZE (result) - AOP_SIZE (right);
8295 /* if unsigned or not an integral type */
8296 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8299 aopPut (AOP (result), zero, offset++);
8303 /* we need to extend the sign :{ */
8304 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8307 emitcode ("rlc", "a");
8308 emitcode ("subb", "a,acc");
8310 aopPut (AOP (result), "a", offset++);
8313 /* we are done hurray !!!! */
8316 freeAsmop (right, NULL, ic, TRUE);
8317 freeAsmop (result, NULL, ic, TRUE);
8321 /*-----------------------------------------------------------------*/
8322 /* genDjnz - generate decrement & jump if not zero instrucion */
8323 /*-----------------------------------------------------------------*/
8325 genDjnz (iCode * ic, iCode * ifx)
8331 /* if the if condition has a false label
8332 then we cannot save */
8336 /* if the minus is not of the form
8338 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8339 !IS_OP_LITERAL (IC_RIGHT (ic)))
8342 if (operandLitValue (IC_RIGHT (ic)) != 1)
8345 /* if the size of this greater than one then no
8347 if (getSize (operandType (IC_RESULT (ic))) > 1)
8350 /* otherwise we can save BIG */
8351 lbl = newiTempLabel (NULL);
8352 lbl1 = newiTempLabel (NULL);
8354 aopOp (IC_RESULT (ic), ic, FALSE);
8356 if (AOP_NEEDSACC(IC_RESULT(ic)))
8358 /* If the result is accessed indirectly via
8359 * the accumulator, we must explicitly write
8360 * it back after the decrement.
8362 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8364 if (strcmp(rByte, "a"))
8366 /* Something is hopelessly wrong */
8367 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8368 __FILE__, __LINE__);
8369 /* We can just give up; the generated code will be inefficient,
8372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8375 emitcode ("dec", "%s", rByte);
8376 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8377 emitcode ("jnz", "%05d$", lbl->key + 100);
8379 else if (IS_AOP_PREG (IC_RESULT (ic)))
8381 emitcode ("dec", "%s",
8382 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8383 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8384 emitcode ("jnz", "%05d$", lbl->key + 100);
8388 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8391 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8392 emitcode ("", "%05d$:", lbl->key + 100);
8393 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8394 emitcode ("", "%05d$:", lbl1->key + 100);
8396 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8401 /*-----------------------------------------------------------------*/
8402 /* genReceive - generate code for a receive iCode */
8403 /*-----------------------------------------------------------------*/
8405 genReceive (iCode * ic)
8407 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8408 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8409 IS_TRUE_SYMOP (IC_RESULT (ic))))
8412 int size = getSize (operandType (IC_RESULT (ic)));
8413 int offset = fReturnSizeMCS51 - size;
8416 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8417 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8420 aopOp (IC_RESULT (ic), ic, FALSE);
8421 size = AOP_SIZE (IC_RESULT (ic));
8425 emitcode ("pop", "acc");
8426 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8433 aopOp (IC_RESULT (ic), ic, FALSE);
8435 assignResultValue (IC_RESULT (ic));
8438 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8441 /*-----------------------------------------------------------------*/
8442 /* gen51Code - generate code for 8051 based controllers */
8443 /*-----------------------------------------------------------------*/
8445 gen51Code (iCode * lic)
8450 lineHead = lineCurr = NULL;
8452 /* print the allocation information */
8454 printAllocInfo (currFunc, codeOutFile);
8455 /* if debug information required */
8456 /* if (options.debug && currFunc) { */
8457 if (options.debug && currFunc)
8459 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8461 if (IS_STATIC (currFunc->etype))
8462 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8464 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8467 /* stack pointer name */
8468 if (options.useXstack)
8474 for (ic = lic; ic; ic = ic->next)
8477 if (cln != ic->lineno)
8482 emitcode ("", "C$%s$%d$%d$%d ==.",
8483 FileBaseName (ic->filename), ic->lineno,
8484 ic->level, ic->block);
8487 emitcode (";", "%s %d", ic->filename, ic->lineno);
8490 /* if the result is marked as
8491 spilt and rematerializable or code for
8492 this has already been generated then
8494 if (resultRemat (ic) || ic->generated)
8497 /* depending on the operation */
8517 /* IPOP happens only when trying to restore a
8518 spilt live range, if there is an ifx statement
8519 following this pop then the if statement might
8520 be using some of the registers being popped which
8521 would destory the contents of the register so
8522 we need to check for this condition and handle it */
8524 ic->next->op == IFX &&
8525 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8526 genIfx (ic->next, ic);
8544 genEndFunction (ic);
8564 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8581 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8585 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8592 /* note these two are xlated by algebraic equivalence
8593 during parsing SDCC.y */
8594 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8595 "got '>=' or '<=' shouldn't have come here");
8599 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8611 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8615 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8619 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8646 case GET_VALUE_AT_ADDRESS:
8647 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8651 if (POINTER_SET (ic))
8652 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8678 addSet (&_G.sendSet, ic);
8687 /* now we are ready to call the
8688 peep hole optimizer */
8689 if (!options.nopeep)
8690 peepHole (&lineHead);
8692 /* now do the actual printing */
8693 printLine (lineHead, codeOutFile);