1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
70 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] =
75 static short rbank = -1;
89 extern int mcs51_ptrRegReq;
90 extern int mcs51_nRegs;
91 extern FILE *codeOutFile;
92 static void saverbank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[MAX_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;
237 /* other wise this is true end of the world */
238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
239 "getFreePtr should never reach here");
243 /*-----------------------------------------------------------------*/
244 /* newAsmop - creates a new asmOp */
245 /*-----------------------------------------------------------------*/
247 newAsmop (short type)
251 aop = Safe_calloc (1, sizeof (asmop));
261 emitcode (";", "Select standard DPTR");
262 emitcode ("mov", "dps, #0x00");
266 emitcode (";", "Select alternate DPTR");
267 emitcode ("mov", "dps, #0x01");
271 /*-----------------------------------------------------------------*/
272 /* pointerCode - returns the code for a pointer type */
273 /*-----------------------------------------------------------------*/
275 pointerCode (sym_link * etype)
278 return PTR_TYPE (SPEC_OCLS (etype));
282 /*-----------------------------------------------------------------*/
283 /* aopForSym - for a true symbol */
284 /*-----------------------------------------------------------------*/
286 aopForSym (iCode * ic, symbol * sym, bool result)
289 memmap *space = SPEC_OCLS (sym->etype);
291 /* if already has one */
295 /* assign depending on the storage class */
296 /* if it is on the stack or indirectly addressable */
297 /* space we need to assign either r0 or r1 to it */
298 if (sym->onStack || sym->iaccess)
300 sym->aop = aop = newAsmop (0);
301 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
302 aop->size = getSize (sym->type);
304 /* now assign the address of the variable to
305 the pointer register */
306 if (aop->type != AOP_STK)
312 emitcode ("push", "acc");
314 emitcode ("mov", "a,_bp");
315 emitcode ("add", "a,#0x%02x",
317 ((char) (sym->stack - _G.nRegsSaved)) :
318 ((char) sym->stack)) & 0xff);
319 emitcode ("mov", "%s,a",
320 aop->aopu.aop_ptr->name);
323 emitcode ("pop", "acc");
326 emitcode ("mov", "%s,#%s",
327 aop->aopu.aop_ptr->name,
329 aop->paged = space->paged;
332 aop->aopu.aop_stk = sym->stack;
336 /* if in bit space */
337 if (IN_BITSPACE (space))
339 sym->aop = aop = newAsmop (AOP_CRY);
340 aop->aopu.aop_dir = sym->rname;
341 aop->size = getSize (sym->type);
344 /* if it is in direct space */
345 if (IN_DIRSPACE (space))
347 sym->aop = aop = newAsmop (AOP_DIR);
348 aop->aopu.aop_dir = sym->rname;
349 aop->size = getSize (sym->type);
353 /* special case for a function */
354 if (IS_FUNC (sym->type))
356 sym->aop = aop = newAsmop (AOP_IMMD);
357 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
358 strcpy (aop->aopu.aop_immd, sym->rname);
359 aop->size = FPTRSIZE;
363 /* only remaining is far space */
364 /* in which case DPTR gets the address */
365 sym->aop = aop = newAsmop (AOP_DPTR);
366 emitcode ("mov", "dptr,#%s", sym->rname);
367 aop->size = getSize (sym->type);
369 /* if it is in code space */
370 if (IN_CODESPACE (space))
376 /*-----------------------------------------------------------------*/
377 /* aopForRemat - rematerialzes an object */
378 /*-----------------------------------------------------------------*/
380 aopForRemat (symbol * sym)
382 iCode *ic = sym->rematiCode;
383 asmop *aop = newAsmop (AOP_IMMD);
389 val += operandLitValue (IC_RIGHT (ic));
390 else if (ic->op == '-')
391 val -= operandLitValue (IC_RIGHT (ic));
395 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
399 sprintf (buffer, "(%s %c 0x%04x)",
400 OP_SYMBOL (IC_LEFT (ic))->rname,
401 val >= 0 ? '+' : '-',
404 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
406 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
407 strcpy (aop->aopu.aop_immd, buffer);
411 /*-----------------------------------------------------------------*/
412 /* regsInCommon - two operands have some registers in common */
413 /*-----------------------------------------------------------------*/
415 regsInCommon (operand * op1, operand * op2)
420 /* if they have registers in common */
421 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
424 sym1 = OP_SYMBOL (op1);
425 sym2 = OP_SYMBOL (op2);
427 if (sym1->nRegs == 0 || sym2->nRegs == 0)
430 for (i = 0; i < sym1->nRegs; i++)
436 for (j = 0; j < sym2->nRegs; j++)
441 if (sym2->regs[j] == sym1->regs[i])
449 /*-----------------------------------------------------------------*/
450 /* operandsEqu - equivalent */
451 /*-----------------------------------------------------------------*/
453 operandsEqu (operand * op1, operand * op2)
457 /* if they not symbols */
458 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
461 sym1 = OP_SYMBOL (op1);
462 sym2 = OP_SYMBOL (op2);
464 /* if both are itemps & one is spilt
465 and the other is not then false */
466 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
467 sym1->isspilt != sym2->isspilt)
470 /* if they are the same */
474 if (strcmp (sym1->rname, sym2->rname) == 0)
478 /* if left is a tmp & right is not */
479 if (IS_ITEMP (op1) &&
482 (sym1->usl.spillLoc == sym2))
485 if (IS_ITEMP (op2) &&
489 (sym2->usl.spillLoc == sym1))
495 /*-----------------------------------------------------------------*/
496 /* sameRegs - two asmops have the same registers */
497 /*-----------------------------------------------------------------*/
499 sameRegs (asmop * aop1, asmop * aop2)
506 if (aop1->type != AOP_REG ||
507 aop2->type != AOP_REG)
510 if (aop1->size != aop2->size)
513 for (i = 0; i < aop1->size; i++)
514 if (aop1->aopu.aop_reg[i] !=
515 aop2->aopu.aop_reg[i])
521 /*-----------------------------------------------------------------*/
522 /* aopOp - allocates an asmop for an operand : */
523 /*-----------------------------------------------------------------*/
525 aopOp (operand * op, iCode * ic, bool result)
534 /* if this a literal */
535 if (IS_OP_LITERAL (op))
537 op->aop = aop = newAsmop (AOP_LIT);
538 aop->aopu.aop_lit = op->operand.valOperand;
539 aop->size = getSize (operandType (op));
543 /* if already has a asmop then continue */
547 /* if the underlying symbol has a aop */
548 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
550 op->aop = OP_SYMBOL (op)->aop;
554 /* if this is a true symbol */
555 if (IS_TRUE_SYMOP (op))
557 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
561 /* this is a temporary : this has
567 e) can be a return use only */
569 sym = OP_SYMBOL (op);
572 /* if the type is a conditional */
573 if (sym->regType == REG_CND)
575 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
580 /* if it is spilt then two situations
582 b) has a spill location */
583 if (sym->isspilt || sym->nRegs == 0)
586 /* rematerialize it NOW */
589 sym->aop = op->aop = aop =
591 aop->size = getSize (sym->type);
598 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
599 aop->size = getSize (sym->type);
600 for (i = 0; i < 2; i++)
601 aop->aopu.aop_str[i] = accUse[i];
608 aop = op->aop = sym->aop = newAsmop (AOP_STR);
609 aop->size = getSize (sym->type);
610 for (i = 0; i < fReturnSizeMCS51; i++)
611 aop->aopu.aop_str[i] = fReturn[i];
615 /* else spill location */
616 sym->aop = op->aop = aop =
617 aopForSym (ic, sym->usl.spillLoc, result);
618 aop->size = getSize (sym->type);
622 /* must be in a register */
623 sym->aop = op->aop = aop = newAsmop (AOP_REG);
624 aop->size = sym->nRegs;
625 for (i = 0; i < sym->nRegs; i++)
626 aop->aopu.aop_reg[i] = sym->regs[i];
629 /*-----------------------------------------------------------------*/
630 /* freeAsmop - free up the asmop given to an operand */
631 /*----------------------------------------------------------------*/
633 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
650 /* depending on the asmop type only three cases need work AOP_RO
651 , AOP_R1 && AOP_STK */
659 emitcode ("pop", "ar0");
663 bitVectUnSetBit (ic->rUsed, R0_IDX);
671 emitcode ("pop", "ar1");
675 bitVectUnSetBit (ic->rUsed, R1_IDX);
681 int stk = aop->aopu.aop_stk + aop->size;
682 bitVectUnSetBit (ic->rUsed, R0_IDX);
683 bitVectUnSetBit (ic->rUsed, R1_IDX);
685 getFreePtr (ic, &aop, FALSE);
689 emitcode ("mov", "a,_bp");
690 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
691 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
695 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
700 emitcode ("pop", "acc");
701 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
704 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
707 freeAsmop (op, NULL, ic, TRUE);
710 emitcode ("pop", "ar0");
716 emitcode ("pop", "ar1");
723 /* all other cases just dealloc */
729 OP_SYMBOL (op)->aop = NULL;
730 /* if the symbol has a spill */
732 SPIL_LOC (op)->aop = NULL;
737 /*-----------------------------------------------------------------*/
738 /* aopGet - for fetching value of the aop */
739 /*-----------------------------------------------------------------*/
741 aopGet (asmop * aop, int offset, bool bit16, bool dname)
746 /* offset is greater than
748 if (offset > (aop->size - 1) &&
749 aop->type != AOP_LIT)
752 /* depending on type */
758 /* if we need to increment it */
759 while (offset > aop->coff)
761 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
765 while (offset < aop->coff)
767 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
774 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
775 return (dname ? "acc" : "a");
777 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
778 rs = Safe_calloc (1, strlen (s) + 1);
785 if (aop->type == AOP_DPTR2)
790 while (offset > aop->coff)
792 emitcode ("inc", "dptr");
796 while (offset < aop->coff)
798 emitcode ("lcall", "__decdptr");
805 emitcode ("clr", "a");
806 emitcode ("movc", "a,@a+dptr");
810 emitcode ("movx", "a,@dptr");
813 if (aop->type == AOP_DPTR2)
818 return (dname ? "acc" : "a");
823 sprintf (s, "#%s", aop->aopu.aop_immd);
825 sprintf (s, "#(%s >> %d)",
831 rs = Safe_calloc (1, strlen (s) + 1);
837 sprintf (s, "(%s + %d)",
841 sprintf (s, "%s", aop->aopu.aop_dir);
842 rs = Safe_calloc (1, strlen (s) + 1);
848 return aop->aopu.aop_reg[offset]->dname;
850 return aop->aopu.aop_reg[offset]->name;
853 emitcode ("clr", "a");
854 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
855 emitcode ("rlc", "a");
856 return (dname ? "acc" : "a");
859 if (!offset && dname)
861 return aop->aopu.aop_str[offset];
864 return aopLiteral (aop->aopu.aop_lit, offset);
868 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
872 return aop->aopu.aop_str[offset];
876 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
877 "aopget got unsupported aop->type");
880 /*-----------------------------------------------------------------*/
881 /* aopPut - puts a string for a aop */
882 /*-----------------------------------------------------------------*/
884 aopPut (asmop * aop, char *s, int offset)
888 if (aop->size && offset > (aop->size - 1))
890 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
891 "aopPut got offset > aop->size");
895 /* will assign value to value */
896 /* depending on where it is ofcourse */
901 sprintf (d, "(%s + %d)",
902 aop->aopu.aop_dir, offset);
904 sprintf (d, "%s", aop->aopu.aop_dir);
907 emitcode ("mov", "%s,%s", d, s);
912 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
913 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
916 strcmp (s, "r0") == 0 ||
917 strcmp (s, "r1") == 0 ||
918 strcmp (s, "r2") == 0 ||
919 strcmp (s, "r3") == 0 ||
920 strcmp (s, "r4") == 0 ||
921 strcmp (s, "r5") == 0 ||
922 strcmp (s, "r6") == 0 ||
923 strcmp (s, "r7") == 0)
924 emitcode ("mov", "%s,%s",
925 aop->aopu.aop_reg[offset]->dname, s);
927 emitcode ("mov", "%s,%s",
928 aop->aopu.aop_reg[offset]->name, s);
935 if (aop->type == AOP_DPTR2)
942 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
943 "aopPut writting to code space");
947 while (offset > aop->coff)
950 emitcode ("inc", "dptr");
953 while (offset < aop->coff)
956 emitcode ("lcall", "__decdptr");
961 /* if not in accumulater */
964 emitcode ("movx", "@dptr,a");
966 if (aop->type == AOP_DPTR2)
974 while (offset > aop->coff)
977 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
979 while (offset < aop->coff)
982 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
989 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
995 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
997 else if (strcmp (s, "r0") == 0 ||
998 strcmp (s, "r1") == 0 ||
999 strcmp (s, "r2") == 0 ||
1000 strcmp (s, "r3") == 0 ||
1001 strcmp (s, "r4") == 0 ||
1002 strcmp (s, "r5") == 0 ||
1003 strcmp (s, "r6") == 0 ||
1004 strcmp (s, "r7") == 0)
1007 sprintf (buffer, "a%s", s);
1008 emitcode ("mov", "@%s,%s",
1009 aop->aopu.aop_ptr->name, buffer);
1012 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1017 if (strcmp (s, "a") == 0)
1018 emitcode ("push", "acc");
1020 emitcode ("push", "%s", s);
1025 /* if bit variable */
1026 if (!aop->aopu.aop_dir)
1028 emitcode ("clr", "a");
1029 emitcode ("rlc", "a");
1034 emitcode ("clr", "%s", aop->aopu.aop_dir);
1036 emitcode ("setb", "%s", aop->aopu.aop_dir);
1037 else if (!strcmp (s, "c"))
1038 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1041 if (strcmp (s, "a"))
1045 #if 0 // jwk: I am not 1000% sure
1047 symbol *lbl = newiTempLabel (NULL);
1048 emitcode ("clr", "c");
1049 emitcode ("jz", "%05d$", lbl->key + 100);
1050 emitcode ("cpl", "c");
1051 emitcode ("", "%05d$:", lbl->key + 100);
1052 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1055 emitcode ("mov", "%s,acc.0", aop->aopu.aop_dir);
1063 if (strcmp (aop->aopu.aop_str[offset], s))
1064 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1069 if (!offset && (strcmp (s, "acc") == 0))
1072 if (strcmp (aop->aopu.aop_str[offset], s))
1073 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1077 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1078 "aopPut got unsupported aop->type");
1086 /*-----------------------------------------------------------------*/
1087 /* pointToEnd :- points to the last byte of the operand */
1088 /*-----------------------------------------------------------------*/
1090 pointToEnd (asmop * aop)
1096 aop->coff = count = (aop->size - 1);
1102 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1106 emitcode ("inc", "dptr");
1113 /*-----------------------------------------------------------------*/
1114 /* reAdjustPreg - points a register back to where it should */
1115 /*-----------------------------------------------------------------*/
1117 reAdjustPreg (asmop * aop)
1120 if ((aop->coff==0) || aop->size <= 1)
1128 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1132 if (aop->type == AOP_DPTR2)
1138 emitcode ("lcall", "__decdptr");
1141 if (aop->type == AOP_DPTR2)
1151 #define AOP(op) op->aop
1152 #define AOP_TYPE(op) AOP(op)->type
1153 #define AOP_SIZE(op) AOP(op)->size
1154 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1155 AOP_TYPE(x) == AOP_R0))
1157 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1158 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1161 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1162 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1163 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1165 /*-----------------------------------------------------------------*/
1166 /* genNotFloat - generates not for float operations */
1167 /*-----------------------------------------------------------------*/
1169 genNotFloat (operand * op, operand * res)
1175 /* we will put 127 in the first byte of
1177 aopPut (AOP (res), "#127", 0);
1178 size = AOP_SIZE (op) - 1;
1181 l = aopGet (op->aop, offset++, FALSE, FALSE);
1186 emitcode ("orl", "a,%s",
1188 offset++, FALSE, FALSE));
1191 tlbl = newiTempLabel (NULL);
1192 aopPut (res->aop, one, 1);
1193 emitcode ("jz", "%05d$", (tlbl->key + 100));
1194 aopPut (res->aop, zero, 1);
1195 emitcode ("", "%05d$:", (tlbl->key + 100));
1197 size = res->aop->size - 2;
1199 /* put zeros in the rest */
1201 aopPut (res->aop, zero, offset++);
1204 /*-----------------------------------------------------------------*/
1205 /* opIsGptr: returns non-zero if the passed operand is */
1206 /* a generic pointer type. */
1207 /*-----------------------------------------------------------------*/
1209 opIsGptr (operand * op)
1211 sym_link *type = operandType (op);
1213 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1220 /*-----------------------------------------------------------------*/
1221 /* getDataSize - get the operand data size */
1222 /*-----------------------------------------------------------------*/
1224 getDataSize (operand * op)
1227 size = AOP_SIZE (op);
1228 if (size == GPTRSIZE)
1230 sym_link *type = operandType (op);
1231 if (IS_GENPTR (type))
1233 /* generic pointer; arithmetic operations
1234 * should ignore the high byte (pointer type).
1242 /*-----------------------------------------------------------------*/
1243 /* outAcc - output Acc */
1244 /*-----------------------------------------------------------------*/
1246 outAcc (operand * result)
1249 size = getDataSize (result);
1252 aopPut (AOP (result), "a", 0);
1255 /* unsigned or positive */
1258 aopPut (AOP (result), zero, offset++);
1263 /*-----------------------------------------------------------------*/
1264 /* outBitC - output a bit C */
1265 /*-----------------------------------------------------------------*/
1267 outBitC (operand * result)
1269 /* if the result is bit */
1270 if (AOP_TYPE (result) == AOP_CRY)
1271 aopPut (AOP (result), "c", 0);
1274 emitcode ("clr", "a");
1275 emitcode ("rlc", "a");
1280 /*-----------------------------------------------------------------*/
1281 /* toBoolean - emit code for orl a,operator(sizeop) */
1282 /*-----------------------------------------------------------------*/
1284 toBoolean (operand * oper)
1286 int size = AOP_SIZE (oper) - 1;
1288 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1290 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1294 /*-----------------------------------------------------------------*/
1295 /* genNot - generate code for ! operation */
1296 /*-----------------------------------------------------------------*/
1301 sym_link *optype = operandType (IC_LEFT (ic));
1303 /* assign asmOps to operand & result */
1304 aopOp (IC_LEFT (ic), ic, FALSE);
1305 aopOp (IC_RESULT (ic), ic, TRUE);
1307 /* if in bit space then a special case */
1308 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1310 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1311 emitcode ("cpl", "c");
1312 outBitC (IC_RESULT (ic));
1316 /* if type float then do float */
1317 if (IS_FLOAT (optype))
1319 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1323 toBoolean (IC_LEFT (ic));
1325 tlbl = newiTempLabel (NULL);
1326 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1327 emitcode ("", "%05d$:", tlbl->key + 100);
1328 outBitC (IC_RESULT (ic));
1331 /* release the aops */
1332 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1337 /*-----------------------------------------------------------------*/
1338 /* genCpl - generate code for complement */
1339 /*-----------------------------------------------------------------*/
1347 /* assign asmOps to operand & result */
1348 aopOp (IC_LEFT (ic), ic, FALSE);
1349 aopOp (IC_RESULT (ic), ic, TRUE);
1351 /* if both are in bit space then
1353 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1354 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1357 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1358 emitcode ("cpl", "c");
1359 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1363 size = AOP_SIZE (IC_RESULT (ic));
1366 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1368 emitcode ("cpl", "a");
1369 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1374 /* release the aops */
1375 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1376 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1379 /*-----------------------------------------------------------------*/
1380 /* genUminusFloat - unary minus for floating points */
1381 /*-----------------------------------------------------------------*/
1383 genUminusFloat (operand * op, operand * result)
1385 int size, offset = 0;
1387 /* for this we just need to flip the
1388 first it then copy the rest in place */
1389 size = AOP_SIZE (op) - 1;
1390 l = aopGet (AOP (op), 3, FALSE, FALSE);
1394 emitcode ("cpl", "acc.7");
1395 aopPut (AOP (result), "a", 3);
1399 aopPut (AOP (result),
1400 aopGet (AOP (op), offset, FALSE, FALSE),
1406 /*-----------------------------------------------------------------*/
1407 /* genUminus - unary minus code generation */
1408 /*-----------------------------------------------------------------*/
1410 genUminus (iCode * ic)
1413 sym_link *optype, *rtype;
1417 aopOp (IC_LEFT (ic), ic, FALSE);
1418 aopOp (IC_RESULT (ic), ic, TRUE);
1420 /* if both in bit space then special
1422 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1423 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1426 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1427 emitcode ("cpl", "c");
1428 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1432 optype = operandType (IC_LEFT (ic));
1433 rtype = operandType (IC_RESULT (ic));
1435 /* if float then do float stuff */
1436 if (IS_FLOAT (optype))
1438 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1442 /* otherwise subtract from zero */
1443 size = AOP_SIZE (IC_LEFT (ic));
1448 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1449 if (!strcmp (l, "a"))
1453 emitcode ("cpl", "a");
1454 emitcode ("addc", "a,#0");
1460 emitcode ("clr", "a");
1461 emitcode ("subb", "a,%s", l);
1463 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1466 /* if any remaining bytes in the result */
1467 /* we just need to propagate the sign */
1468 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1470 emitcode ("rlc", "a");
1471 emitcode ("subb", "a,acc");
1473 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1477 /* release the aops */
1478 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* saveRegisters - will look for a call and save the registers */
1484 /*-----------------------------------------------------------------*/
1486 saveRegisters (iCode * lic)
1494 for (ic = lic; ic; ic = ic->next)
1495 if (ic->op == CALL || ic->op == PCALL)
1500 fprintf (stderr, "found parameter push with no function call\n");
1504 /* if the registers have been saved already then
1506 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1509 /* find the registers in use at this time
1510 and push them away to safety */
1511 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1515 if (options.useXstack)
1517 if (bitVectBitValue (rsave, R0_IDX))
1518 emitcode ("mov", "b,r0");
1519 emitcode ("mov", "r0,%s", spname);
1520 for (i = 0; i < mcs51_nRegs; i++)
1522 if (bitVectBitValue (rsave, i))
1525 emitcode ("mov", "a,b");
1527 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1528 emitcode ("movx", "@r0,a");
1529 emitcode ("inc", "r0");
1532 emitcode ("mov", "%s,r0", spname);
1533 if (bitVectBitValue (rsave, R0_IDX))
1534 emitcode ("mov", "r0,b");
1537 for (i = 0; i < mcs51_nRegs; i++)
1539 if (bitVectBitValue (rsave, i))
1540 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1543 detype = getSpec (operandType (IC_LEFT (ic)));
1545 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1546 IS_ISR (currFunc->etype) &&
1549 saverbank (SPEC_BANK (detype), ic, TRUE);
1552 /*-----------------------------------------------------------------*/
1553 /* unsaveRegisters - pop the pushed registers */
1554 /*-----------------------------------------------------------------*/
1556 unsaveRegisters (iCode * ic)
1560 /* find the registers in use at this time
1561 and push them away to safety */
1562 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1565 if (options.useXstack)
1567 emitcode ("mov", "r0,%s", spname);
1568 for (i = mcs51_nRegs; i >= 0; i--)
1570 if (bitVectBitValue (rsave, i))
1572 emitcode ("dec", "r0");
1573 emitcode ("movx", "a,@r0");
1575 emitcode ("mov", "b,a");
1577 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1581 emitcode ("mov", "%s,r0", spname);
1582 if (bitVectBitValue (rsave, R0_IDX))
1583 emitcode ("mov", "r0,b");
1586 for (i = mcs51_nRegs; i >= 0; i--)
1588 if (bitVectBitValue (rsave, i))
1589 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1595 /*-----------------------------------------------------------------*/
1597 /*-----------------------------------------------------------------*/
1599 pushSide (operand * oper, int size)
1604 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1605 if (AOP_TYPE (oper) != AOP_REG &&
1606 AOP_TYPE (oper) != AOP_DIR &&
1609 emitcode ("mov", "a,%s", l);
1610 emitcode ("push", "acc");
1613 emitcode ("push", "%s", l);
1617 /*-----------------------------------------------------------------*/
1618 /* assignResultValue - */
1619 /*-----------------------------------------------------------------*/
1621 assignResultValue (operand * oper)
1624 int size = AOP_SIZE (oper);
1627 aopPut (AOP (oper), fReturn[offset], offset);
1633 /*-----------------------------------------------------------------*/
1634 /* genXpush - pushes onto the external stack */
1635 /*-----------------------------------------------------------------*/
1637 genXpush (iCode * ic)
1639 asmop *aop = newAsmop (0);
1641 int size, offset = 0;
1643 aopOp (IC_LEFT (ic), ic, FALSE);
1644 r = getFreePtr (ic, &aop, FALSE);
1647 emitcode ("mov", "%s,_spx", r->name);
1649 size = AOP_SIZE (IC_LEFT (ic));
1653 char *l = aopGet (AOP (IC_LEFT (ic)),
1654 offset++, FALSE, FALSE);
1656 emitcode ("movx", "@%s,a", r->name);
1657 emitcode ("inc", "%s", r->name);
1662 emitcode ("mov", "_spx,%s", r->name);
1664 freeAsmop (NULL, aop, ic, TRUE);
1665 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1668 /*-----------------------------------------------------------------*/
1669 /* genIpush - genrate code for pushing this gets a little complex */
1670 /*-----------------------------------------------------------------*/
1672 genIpush (iCode * ic)
1674 int size, offset = 0;
1678 /* if this is not a parm push : ie. it is spill push
1679 and spill push is always done on the local stack */
1683 /* and the item is spilt then do nothing */
1684 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1687 aopOp (IC_LEFT (ic), ic, FALSE);
1688 size = AOP_SIZE (IC_LEFT (ic));
1689 /* push it on the stack */
1692 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1698 emitcode ("push", "%s", l);
1703 /* this is a paramter push: in this case we call
1704 the routine to find the call and save those
1705 registers that need to be saved */
1708 /* if use external stack then call the external
1709 stack pushing routine */
1710 if (options.useXstack)
1716 /* then do the push */
1717 aopOp (IC_LEFT (ic), ic, FALSE);
1720 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1721 size = AOP_SIZE (IC_LEFT (ic));
1725 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1726 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1727 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1730 emitcode ("mov", "a,%s", l);
1731 emitcode ("push", "acc");
1734 emitcode ("push", "%s", l);
1737 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1740 /*-----------------------------------------------------------------*/
1741 /* genIpop - recover the registers: can happen only for spilling */
1742 /*-----------------------------------------------------------------*/
1744 genIpop (iCode * ic)
1749 /* if the temp was not pushed then */
1750 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1753 aopOp (IC_LEFT (ic), ic, FALSE);
1754 size = AOP_SIZE (IC_LEFT (ic));
1755 offset = (size - 1);
1757 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1760 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1763 /*-----------------------------------------------------------------*/
1764 /* unsaverbank - restores the resgister bank from stack */
1765 /*-----------------------------------------------------------------*/
1767 unsaverbank (int bank, iCode * ic, bool popPsw)
1775 if (options.useXstack)
1778 r = getFreePtr (ic, &aop, FALSE);
1781 emitcode ("mov", "%s,_spx", r->name);
1782 emitcode ("movx", "a,@%s", r->name);
1783 emitcode ("mov", "psw,a");
1784 emitcode ("dec", "%s", r->name);
1788 emitcode ("pop", "psw");
1791 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1793 if (options.useXstack)
1795 emitcode ("movx", "a,@%s", r->name);
1796 emitcode ("mov", "(%s+%d),a",
1797 regs8051[i].base, 8 * bank + regs8051[i].offset);
1798 emitcode ("dec", "%s", r->name);
1802 emitcode ("pop", "(%s+%d)",
1803 regs8051[i].base, 8 * bank + regs8051[i].offset);
1806 if (options.useXstack)
1809 emitcode ("mov", "_spx,%s", r->name);
1810 freeAsmop (NULL, aop, ic, TRUE);
1815 /*-----------------------------------------------------------------*/
1816 /* saverbank - saves an entire register bank on the stack */
1817 /*-----------------------------------------------------------------*/
1819 saverbank (int bank, iCode * ic, bool pushPsw)
1825 if (options.useXstack)
1829 r = getFreePtr (ic, &aop, FALSE);
1830 emitcode ("mov", "%s,_spx", r->name);
1834 for (i = 0; i < mcs51_nRegs; i++)
1836 if (options.useXstack)
1838 emitcode ("inc", "%s", r->name);
1839 emitcode ("mov", "a,(%s+%d)",
1840 regs8051[i].base, 8 * bank + regs8051[i].offset);
1841 emitcode ("movx", "@%s,a", r->name);
1844 emitcode ("push", "(%s+%d)",
1845 regs8051[i].base, 8 * bank + regs8051[i].offset);
1850 if (options.useXstack)
1852 emitcode ("mov", "a,psw");
1853 emitcode ("movx", "@%s,a", r->name);
1854 emitcode ("inc", "%s", r->name);
1855 emitcode ("mov", "_spx,%s", r->name);
1856 freeAsmop (NULL, aop, ic, TRUE);
1860 emitcode ("push", "psw");
1862 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1868 /*-----------------------------------------------------------------*/
1869 /* genCall - generates a call statement */
1870 /*-----------------------------------------------------------------*/
1872 genCall (iCode * ic)
1876 /* if caller saves & we have not saved then */
1880 /* if we are calling a function that is not using
1881 the same register bank then we need to save the
1882 destination registers on the stack */
1883 detype = getSpec (operandType (IC_LEFT (ic)));
1885 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1886 IS_ISR (currFunc->etype) &&
1889 saverbank (SPEC_BANK (detype), ic, TRUE);
1891 /* if send set is not empty the assign */
1896 for (sic = setFirstItem (_G.sendSet); sic;
1897 sic = setNextItem (_G.sendSet))
1899 int size, offset = 0;
1900 aopOp (IC_LEFT (sic), sic, FALSE);
1901 size = AOP_SIZE (IC_LEFT (sic));
1904 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1906 if (strcmp (l, fReturn[offset]))
1907 emitcode ("mov", "%s,%s",
1912 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1917 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1918 OP_SYMBOL (IC_LEFT (ic))->rname :
1919 OP_SYMBOL (IC_LEFT (ic))->name));
1921 /* if we need assign a result value */
1922 if ((IS_ITEMP (IC_RESULT (ic)) &&
1923 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1924 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1925 IS_TRUE_SYMOP (IC_RESULT (ic)))
1929 aopOp (IC_RESULT (ic), ic, FALSE);
1932 assignResultValue (IC_RESULT (ic));
1934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1937 /* adjust the stack for parameters if
1942 if (ic->parmBytes > 3)
1944 emitcode ("mov", "a,%s", spname);
1945 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1946 emitcode ("mov", "%s,a", spname);
1949 for (i = 0; i < ic->parmBytes; i++)
1950 emitcode ("dec", "%s", spname);
1954 /* if register bank was saved then pop them */
1956 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1958 /* if we hade saved some registers then unsave them */
1959 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1960 unsaveRegisters (ic);
1965 /*-----------------------------------------------------------------*/
1966 /* genPcall - generates a call by pointer statement */
1967 /*-----------------------------------------------------------------*/
1969 genPcall (iCode * ic)
1972 symbol *rlbl = newiTempLabel (NULL);
1975 /* if caller saves & we have not saved then */
1979 /* if we are calling a function that is not using
1980 the same register bank then we need to save the
1981 destination registers on the stack */
1982 detype = getSpec (operandType (IC_LEFT (ic)));
1984 IS_ISR (currFunc->etype) &&
1985 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1986 saverbank (SPEC_BANK (detype), ic, TRUE);
1989 /* push the return address on to the stack */
1990 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1991 emitcode ("push", "acc");
1992 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1993 emitcode ("push", "acc");
1995 /* now push the calling address */
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1998 pushSide (IC_LEFT (ic), FPTRSIZE);
2000 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2002 /* if send set is not empty the assign */
2007 for (sic = setFirstItem (_G.sendSet); sic;
2008 sic = setNextItem (_G.sendSet))
2010 int size, offset = 0;
2011 aopOp (IC_LEFT (sic), sic, FALSE);
2012 size = AOP_SIZE (IC_LEFT (sic));
2015 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2017 if (strcmp (l, fReturn[offset]))
2018 emitcode ("mov", "%s,%s",
2023 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2028 emitcode ("ret", "");
2029 emitcode ("", "%05d$:", (rlbl->key + 100));
2032 /* if we need assign a result value */
2033 if ((IS_ITEMP (IC_RESULT (ic)) &&
2034 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2035 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2036 IS_TRUE_SYMOP (IC_RESULT (ic)))
2040 aopOp (IC_RESULT (ic), ic, FALSE);
2043 assignResultValue (IC_RESULT (ic));
2045 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2048 /* adjust the stack for parameters if
2053 if (ic->parmBytes > 3)
2055 emitcode ("mov", "a,%s", spname);
2056 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2057 emitcode ("mov", "%s,a", spname);
2060 for (i = 0; i < ic->parmBytes; i++)
2061 emitcode ("dec", "%s", spname);
2065 /* if register bank was saved then unsave them */
2067 (SPEC_BANK (currFunc->etype) !=
2068 SPEC_BANK (detype)))
2069 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2071 /* if we hade saved some registers then
2074 unsaveRegisters (ic);
2078 /*-----------------------------------------------------------------*/
2079 /* resultRemat - result is rematerializable */
2080 /*-----------------------------------------------------------------*/
2082 resultRemat (iCode * ic)
2084 if (SKIP_IC (ic) || ic->op == IFX)
2087 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2089 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2090 if (sym->remat && !POINTER_SET (ic))
2097 #if defined(__BORLANDC__) || defined(_MSC_VER)
2098 #define STRCASECMP stricmp
2100 #define STRCASECMP strcasecmp
2103 /*-----------------------------------------------------------------*/
2104 /* inExcludeList - return 1 if the string is in exclude Reg list */
2105 /*-----------------------------------------------------------------*/
2107 inExcludeList (char *s)
2111 if (options.excludeRegs[i] &&
2112 STRCASECMP (options.excludeRegs[i], "none") == 0)
2115 for (i = 0; options.excludeRegs[i]; i++)
2117 if (options.excludeRegs[i] &&
2118 STRCASECMP (s, options.excludeRegs[i]) == 0)
2124 /*-----------------------------------------------------------------*/
2125 /* genFunction - generated code for function entry */
2126 /*-----------------------------------------------------------------*/
2128 genFunction (iCode * ic)
2134 /* create the function header */
2135 emitcode (";", "-----------------------------------------");
2136 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2137 emitcode (";", "-----------------------------------------");
2139 emitcode ("", "%s:", sym->rname);
2140 fetype = getSpec (operandType (IC_LEFT (ic)));
2142 /* if critical function then turn interrupts off */
2143 if (SPEC_CRTCL (fetype))
2144 emitcode ("clr", "ea");
2146 /* here we need to generate the equates for the
2147 register bank if required */
2148 if (SPEC_BANK (fetype) != rbank)
2152 rbank = SPEC_BANK (fetype);
2153 for (i = 0; i < mcs51_nRegs; i++)
2155 if (strcmp (regs8051[i].base, "0") == 0)
2156 emitcode ("", "%s = 0x%02x",
2158 8 * rbank + regs8051[i].offset);
2160 emitcode ("", "%s = %s + 0x%02x",
2163 8 * rbank + regs8051[i].offset);
2167 /* if this is an interrupt service routine then
2168 save acc, b, dpl, dph */
2169 if (IS_ISR (sym->etype))
2172 if (!inExcludeList ("acc"))
2173 emitcode ("push", "acc");
2174 if (!inExcludeList ("b"))
2175 emitcode ("push", "b");
2176 if (!inExcludeList ("dpl"))
2177 emitcode ("push", "dpl");
2178 if (!inExcludeList ("dph"))
2179 emitcode ("push", "dph");
2180 /* if this isr has no bank i.e. is going to
2181 run with bank 0 , then we need to save more
2183 if (!SPEC_BANK (sym->etype))
2186 /* if this function does not call any other
2187 function then we can be economical and
2188 save only those registers that are used */
2193 /* if any registers used */
2196 /* save the registers used */
2197 for (i = 0; i < sym->regsUsed->size; i++)
2199 if (bitVectBitValue (sym->regsUsed, i) ||
2200 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2201 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2208 /* this function has a function call cannot
2209 determines register usage so we will have the
2211 saverbank (0, ic, FALSE);
2217 /* if callee-save to be used for this function
2218 then save the registers being used in this function */
2219 if (sym->calleeSave)
2223 /* if any registers used */
2226 /* save the registers used */
2227 for (i = 0; i < sym->regsUsed->size; i++)
2229 if (bitVectBitValue (sym->regsUsed, i) ||
2230 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2232 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2240 /* set the register bank to the desired value */
2241 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2243 emitcode ("push", "psw");
2244 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2247 if (IS_RENT (sym->etype) || options.stackAuto)
2250 if (options.useXstack)
2252 emitcode ("mov", "r0,%s", spname);
2253 emitcode ("mov", "a,_bp");
2254 emitcode ("movx", "@r0,a");
2255 emitcode ("inc", "%s", spname);
2259 /* set up the stack */
2260 emitcode ("push", "_bp"); /* save the callers stack */
2262 emitcode ("mov", "_bp,%s", spname);
2265 /* adjust the stack for the function */
2271 werror (W_STACK_OVERFLOW, sym->name);
2273 if (i > 3 && sym->recvSize < 4)
2276 emitcode ("mov", "a,sp");
2277 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2278 emitcode ("mov", "sp,a");
2283 emitcode ("inc", "sp");
2289 emitcode ("mov", "a,_spx");
2290 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2291 emitcode ("mov", "_spx,a");
2296 /*-----------------------------------------------------------------*/
2297 /* genEndFunction - generates epilogue for functions */
2298 /*-----------------------------------------------------------------*/
2300 genEndFunction (iCode * ic)
2302 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2304 if (IS_RENT (sym->etype) || options.stackAuto)
2306 emitcode ("mov", "%s,_bp", spname);
2309 /* if use external stack but some variables were
2310 added to the local stack then decrement the
2312 if (options.useXstack && sym->stack)
2314 emitcode ("mov", "a,sp");
2315 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2316 emitcode ("mov", "sp,a");
2320 if ((IS_RENT (sym->etype) || options.stackAuto))
2322 if (options.useXstack)
2324 emitcode ("mov", "r0,%s", spname);
2325 emitcode ("movx", "a,@r0");
2326 emitcode ("mov", "_bp,a");
2327 emitcode ("dec", "%s", spname);
2331 emitcode ("pop", "_bp");
2335 /* restore the register bank */
2336 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2337 emitcode ("pop", "psw");
2339 if (IS_ISR (sym->etype))
2342 /* now we need to restore the registers */
2343 /* if this isr has no bank i.e. is going to
2344 run with bank 0 , then we need to save more
2346 if (!SPEC_BANK (sym->etype))
2349 /* if this function does not call any other
2350 function then we can be economical and
2351 save only those registers that are used */
2356 /* if any registers used */
2359 /* save the registers used */
2360 for (i = sym->regsUsed->size; i >= 0; i--)
2362 if (bitVectBitValue (sym->regsUsed, i) ||
2363 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2364 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2371 /* this function has a function call cannot
2372 determines register usage so we will have the
2374 unsaverbank (0, ic, FALSE);
2378 if (!inExcludeList ("dph"))
2379 emitcode ("pop", "dph");
2380 if (!inExcludeList ("dpl"))
2381 emitcode ("pop", "dpl");
2382 if (!inExcludeList ("b"))
2383 emitcode ("pop", "b");
2384 if (!inExcludeList ("acc"))
2385 emitcode ("pop", "acc");
2387 if (SPEC_CRTCL (sym->etype))
2388 emitcode ("setb", "ea");
2390 /* if debug then send end of function */
2391 /* if (options.debug && currFunc) { */
2395 emitcode ("", "C$%s$%d$%d$%d ==.",
2396 FileBaseName (ic->filename), currFunc->lastLine,
2397 ic->level, ic->block);
2398 if (IS_STATIC (currFunc->etype))
2399 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2401 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2405 emitcode ("reti", "");
2409 if (SPEC_CRTCL (sym->etype))
2410 emitcode ("setb", "ea");
2412 if (sym->calleeSave)
2416 /* if any registers used */
2419 /* save the registers used */
2420 for (i = sym->regsUsed->size; i >= 0; i--)
2422 if (bitVectBitValue (sym->regsUsed, i) ||
2423 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2424 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2430 /* if debug then send end of function */
2434 emitcode ("", "C$%s$%d$%d$%d ==.",
2435 FileBaseName (ic->filename), currFunc->lastLine,
2436 ic->level, ic->block);
2437 if (IS_STATIC (currFunc->etype))
2438 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2440 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2444 emitcode ("ret", "");
2449 /*-----------------------------------------------------------------*/
2450 /* genRet - generate code for return statement */
2451 /*-----------------------------------------------------------------*/
2455 int size, offset = 0, pushed = 0;
2457 /* if we have no return value then
2458 just generate the "ret" */
2462 /* we have something to return then
2463 move the return value into place */
2464 aopOp (IC_LEFT (ic), ic, FALSE);
2465 size = AOP_SIZE (IC_LEFT (ic));
2470 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2473 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2475 emitcode ("push", "%s", l);
2480 l = aopGet (AOP (IC_LEFT (ic)), offset,
2482 if (strcmp (fReturn[offset], l))
2483 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2492 if (strcmp (fReturn[pushed], "a"))
2493 emitcode ("pop", fReturn[pushed]);
2495 emitcode ("pop", "acc");
2498 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2501 /* generate a jump to the return label
2502 if the next is not the return statement */
2503 if (!(ic->next && ic->next->op == LABEL &&
2504 IC_LABEL (ic->next) == returnLabel))
2506 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2510 /*-----------------------------------------------------------------*/
2511 /* genLabel - generates a label */
2512 /*-----------------------------------------------------------------*/
2514 genLabel (iCode * ic)
2516 /* special case never generate */
2517 if (IC_LABEL (ic) == entryLabel)
2520 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2523 /*-----------------------------------------------------------------*/
2524 /* genGoto - generates a ljmp */
2525 /*-----------------------------------------------------------------*/
2527 genGoto (iCode * ic)
2529 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2532 /*-----------------------------------------------------------------*/
2533 /* findLabelBackwards: walks back through the iCode chain looking */
2534 /* for the given label. Returns number of iCode instructions */
2535 /* between that label and given ic. */
2536 /* Returns zero if label not found. */
2537 /*-----------------------------------------------------------------*/
2539 findLabelBackwards (iCode * ic, int key)
2548 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2550 /* printf("findLabelBackwards = %d\n", count); */
2558 /*-----------------------------------------------------------------*/
2559 /* genPlusIncr :- does addition with increment if possible */
2560 /*-----------------------------------------------------------------*/
2562 genPlusIncr (iCode * ic)
2564 unsigned int icount;
2565 unsigned int size = getDataSize (IC_RESULT (ic));
2567 /* will try to generate an increment */
2568 /* if the right side is not a literal
2570 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2573 /* if the literal value of the right hand side
2574 is greater than 4 then it is not worth it */
2575 if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2578 /* if increment 16 bits in register */
2579 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2587 /* If the next instruction is a goto and the goto target
2588 * is < 10 instructions previous to this, we can generate
2589 * jumps straight to that target.
2591 if (ic->next && ic->next->op == GOTO
2592 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2593 && labelRange <= 10)
2595 emitcode (";", "tail increment optimized");
2596 tlbl = IC_LABEL (ic->next);
2601 tlbl = newiTempLabel (NULL);
2604 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2605 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2606 IS_AOP_PREG (IC_RESULT (ic)))
2607 emitcode ("cjne", "%s,#0x00,%05d$"
2608 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2612 emitcode ("clr", "a");
2613 emitcode ("cjne", "a,%s,%05d$"
2614 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2618 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2621 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2622 IS_AOP_PREG (IC_RESULT (ic)))
2623 emitcode ("cjne", "%s,#0x00,%05d$"
2624 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2627 emitcode ("cjne", "a,%s,%05d$"
2628 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2631 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2635 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2636 IS_AOP_PREG (IC_RESULT (ic)))
2637 emitcode ("cjne", "%s,#0x00,%05d$"
2638 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2642 emitcode ("cjne", "a,%s,%05d$"
2643 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2646 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2651 emitcode ("", "%05d$:", tlbl->key + 100);
2656 /* if the sizes are greater than 1 then we cannot */
2657 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2658 AOP_SIZE (IC_LEFT (ic)) > 1)
2661 /* we can if the aops of the left & result match or
2662 if they are in registers and the registers are the
2664 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2669 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2670 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2671 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2677 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2686 /*-----------------------------------------------------------------*/
2687 /* outBitAcc - output a bit in acc */
2688 /*-----------------------------------------------------------------*/
2690 outBitAcc (operand * result)
2692 symbol *tlbl = newiTempLabel (NULL);
2693 /* if the result is a bit */
2694 if (AOP_TYPE (result) == AOP_CRY)
2696 aopPut (AOP (result), "a", 0);
2700 emitcode ("jz", "%05d$", tlbl->key + 100);
2701 emitcode ("mov", "a,%s", one);
2702 emitcode ("", "%05d$:", tlbl->key + 100);
2707 /*-----------------------------------------------------------------*/
2708 /* genPlusBits - generates code for addition of two bits */
2709 /*-----------------------------------------------------------------*/
2711 genPlusBits (iCode * ic)
2713 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2715 symbol *lbl = newiTempLabel (NULL);
2716 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2717 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2718 emitcode ("cpl", "c");
2719 emitcode ("", "%05d$:", (lbl->key + 100));
2720 outBitC (IC_RESULT (ic));
2724 emitcode ("clr", "a");
2725 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2726 emitcode ("rlc", "a");
2727 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2728 emitcode ("addc", "a,#0x00");
2729 outAcc (IC_RESULT (ic));
2734 /* This is the original version of this code.
2736 * This is being kept around for reference,
2737 * because I am not entirely sure I got it right...
2740 adjustArithmeticResult (iCode * ic)
2742 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2743 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2744 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2745 aopPut (AOP (IC_RESULT (ic)),
2746 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2749 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2750 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2751 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2752 aopPut (AOP (IC_RESULT (ic)),
2753 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2756 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2757 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2758 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2759 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2760 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2763 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2764 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2768 /* This is the pure and virtuous version of this code.
2769 * I'm pretty certain it's right, but not enough to toss the old
2773 adjustArithmeticResult (iCode * ic)
2775 if (opIsGptr (IC_RESULT (ic)) &&
2776 opIsGptr (IC_LEFT (ic)) &&
2777 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2779 aopPut (AOP (IC_RESULT (ic)),
2780 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2784 if (opIsGptr (IC_RESULT (ic)) &&
2785 opIsGptr (IC_RIGHT (ic)) &&
2786 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2788 aopPut (AOP (IC_RESULT (ic)),
2789 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2793 if (opIsGptr (IC_RESULT (ic)) &&
2794 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2795 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2796 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2797 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2800 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2801 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2806 /*-----------------------------------------------------------------*/
2807 /* genPlus - generates code for addition */
2808 /*-----------------------------------------------------------------*/
2810 genPlus (iCode * ic)
2812 int size, offset = 0;
2814 /* special cases :- */
2816 aopOp (IC_LEFT (ic), ic, FALSE);
2817 aopOp (IC_RIGHT (ic), ic, FALSE);
2818 aopOp (IC_RESULT (ic), ic, TRUE);
2820 /* if literal, literal on the right or
2821 if left requires ACC or right is already
2823 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2824 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2825 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2827 operand *t = IC_RIGHT (ic);
2828 IC_RIGHT (ic) = IC_LEFT (ic);
2832 /* if both left & right are in bit
2834 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2835 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2841 /* if left in bit space & right literal */
2842 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2843 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2845 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2846 /* if result in bit space */
2847 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2849 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2850 emitcode ("cpl", "c");
2851 outBitC (IC_RESULT (ic));
2855 size = getDataSize (IC_RESULT (ic));
2858 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2859 emitcode ("addc", "a,#00");
2860 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2866 /* if I can do an increment instead
2867 of add then GOOD for ME */
2868 if (genPlusIncr (ic) == TRUE)
2871 size = getDataSize (IC_RESULT (ic));
2875 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2877 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2879 emitcode ("add", "a,%s",
2880 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2882 emitcode ("addc", "a,%s",
2883 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2887 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2889 emitcode ("add", "a,%s",
2890 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2892 emitcode ("addc", "a,%s",
2893 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2895 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2898 adjustArithmeticResult (ic);
2901 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2902 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2903 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2906 /*-----------------------------------------------------------------*/
2907 /* genMinusDec :- does subtraction with deccrement if possible */
2908 /*-----------------------------------------------------------------*/
2910 genMinusDec (iCode * ic)
2912 unsigned int icount;
2913 unsigned int size = getDataSize (IC_RESULT (ic));
2915 /* will try to generate an increment */
2916 /* if the right side is not a literal
2918 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2921 /* if the literal value of the right hand side
2922 is greater than 4 then it is not worth it */
2923 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2926 /* if decrement 16 bits in register */
2927 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2935 /* If the next instruction is a goto and the goto target
2936 * is <= 10 instructions previous to this, we can generate
2937 * jumps straight to that target.
2939 if (ic->next && ic->next->op == GOTO
2940 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2941 && labelRange <= 10)
2943 emitcode (";", "tail decrement optimized");
2944 tlbl = IC_LABEL (ic->next);
2949 tlbl = newiTempLabel (NULL);
2953 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2954 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2955 IS_AOP_PREG (IC_RESULT (ic)))
2956 emitcode ("cjne", "%s,#0xff,%05d$"
2957 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2961 emitcode ("mov", "a,#0xff");
2962 emitcode ("cjne", "a,%s,%05d$"
2963 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2966 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2969 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2970 IS_AOP_PREG (IC_RESULT (ic)))
2971 emitcode ("cjne", "%s,#0xff,%05d$"
2972 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2976 emitcode ("cjne", "a,%s,%05d$"
2977 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2980 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2984 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2985 IS_AOP_PREG (IC_RESULT (ic)))
2986 emitcode ("cjne", "%s,#0xff,%05d$"
2987 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2991 emitcode ("cjne", "a,%s,%05d$"
2992 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2995 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2999 emitcode ("", "%05d$:", tlbl->key + 100);
3004 /* if the sizes are greater than 1 then we cannot */
3005 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3006 AOP_SIZE (IC_LEFT (ic)) > 1)
3009 /* we can if the aops of the left & result match or
3010 if they are in registers and the registers are the
3012 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3016 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3024 /*-----------------------------------------------------------------*/
3025 /* addSign - complete with sign */
3026 /*-----------------------------------------------------------------*/
3028 addSign (operand * result, int offset, int sign)
3030 int size = (getDataSize (result) - offset);
3035 emitcode ("rlc", "a");
3036 emitcode ("subb", "a,acc");
3038 aopPut (AOP (result), "a", offset++);
3042 aopPut (AOP (result), zero, offset++);
3046 /*-----------------------------------------------------------------*/
3047 /* genMinusBits - generates code for subtraction of two bits */
3048 /*-----------------------------------------------------------------*/
3050 genMinusBits (iCode * ic)
3052 symbol *lbl = newiTempLabel (NULL);
3053 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3055 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3056 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3057 emitcode ("cpl", "c");
3058 emitcode ("", "%05d$:", (lbl->key + 100));
3059 outBitC (IC_RESULT (ic));
3063 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3064 emitcode ("subb", "a,acc");
3065 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3066 emitcode ("inc", "a");
3067 emitcode ("", "%05d$:", (lbl->key + 100));
3068 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3069 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3073 /*-----------------------------------------------------------------*/
3074 /* genMinus - generates code for subtraction */
3075 /*-----------------------------------------------------------------*/
3077 genMinus (iCode * ic)
3079 int size, offset = 0;
3080 unsigned long lit = 0L;
3082 aopOp (IC_LEFT (ic), ic, FALSE);
3083 aopOp (IC_RIGHT (ic), ic, FALSE);
3084 aopOp (IC_RESULT (ic), ic, TRUE);
3086 /* special cases :- */
3087 /* if both left & right are in bit space */
3088 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3089 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3095 /* if I can do an decrement instead
3096 of subtract then GOOD for ME */
3097 if (genMinusDec (ic) == TRUE)
3100 size = getDataSize (IC_RESULT (ic));
3102 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3108 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3112 /* if literal, add a,#-lit, else normal subb */
3115 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3116 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3117 emitcode ("subb", "a,%s",
3118 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3121 /* first add without previous c */
3123 emitcode ("add", "a,#0x%02x",
3124 (unsigned int) (lit & 0x0FFL));
3126 emitcode ("addc", "a,#0x%02x",
3127 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3129 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3132 adjustArithmeticResult (ic);
3135 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3136 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3137 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3141 /*-----------------------------------------------------------------*/
3142 /* genMultbits :- multiplication of bits */
3143 /*-----------------------------------------------------------------*/
3145 genMultbits (operand * left,
3149 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3150 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3155 /*-----------------------------------------------------------------*/
3156 /* genMultOneByte : 8*8=8/16 bit multiplication */
3157 /*-----------------------------------------------------------------*/
3160 genMultOneByte (operand * left,
3164 sym_link *opetype = operandType (result);
3169 /* (if two literals, the value is computed before) */
3170 /* if one literal, literal on the right */
3171 if (AOP_TYPE (left) == AOP_LIT)
3178 size = AOP_SIZE (result);
3179 /* signed or unsigned */
3180 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3181 l = aopGet (AOP (left), 0, FALSE, FALSE);
3183 emitcode ("mul", "ab");
3184 /* if result size = 1, mul signed = mul unsigned */
3185 aopPut (AOP (result), "a", 0);
3188 if (SPEC_USIGN (opetype))
3190 aopPut (AOP (result), "b", 1);
3192 /* for filling the MSBs */
3193 emitcode ("clr", "a");
3197 emitcode ("mov", "a,b");
3199 /* adjust the MSB if left or right neg */
3201 /* if one literal */
3202 if (AOP_TYPE (right) == AOP_LIT)
3204 /* AND literal negative */
3205 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3207 /* adjust MSB (c==0 after mul) */
3208 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3213 lbl = newiTempLabel (NULL);
3214 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3215 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3216 emitcode ("", "%05d$:", (lbl->key + 100));
3217 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3218 lbl = newiTempLabel (NULL);
3219 emitcode ("jc", "%05d$", (lbl->key + 100));
3220 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3221 emitcode ("", "%05d$:", (lbl->key + 100));
3224 lbl = newiTempLabel (NULL);
3225 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3226 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3227 emitcode ("", "%05d$:", (lbl->key + 100));
3228 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3229 lbl = newiTempLabel (NULL);
3230 emitcode ("jc", "%05d$", (lbl->key + 100));
3231 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3232 emitcode ("", "%05d$:", (lbl->key + 100));
3234 aopPut (AOP (result), "a", 1);
3238 emitcode ("rlc", "a");
3239 emitcode ("subb", "a,acc");
3246 aopPut (AOP (result), "a", offset++);
3251 genMultOneByte (operand * left,
3255 sym_link *opetype = operandType (result);
3257 int size=AOP_SIZE(result);
3259 //emitcode (";",__FUNCTION__);
3260 if (size<1 || size>2) {
3261 // this should never happen
3262 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3263 AOP_SIZE(result), __FUNCTION__, lineno);
3267 /* (if two literals: the value is computed before) */
3268 /* if one literal, literal on the right */
3269 if (AOP_TYPE (left) == AOP_LIT)
3274 //emitcode (";", "swapped left and right");
3277 if (SPEC_USIGN(opetype)
3278 // ignore the sign of left and right, what else can we do?
3279 || (SPEC_USIGN(operandType(left)) &&
3280 SPEC_USIGN(operandType(right)))) {
3281 // just an unsigned 8*8=8/16 multiply
3282 //emitcode (";","unsigned");
3283 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3284 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3285 emitcode ("mul", "ab");
3286 aopPut (AOP (result), "a", 0);
3288 aopPut (AOP (result), "b", 1);
3293 // we have to do a signed multiply
3295 //emitcode (";", "signed");
3296 emitcode ("clr", "F0"); // reset sign flag
3297 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3298 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3300 lbl=newiTempLabel(NULL);
3301 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3302 // left side is negative, 8-bit two's complement, this fails for -128
3303 emitcode ("setb", "F0"); // set sign flag
3304 emitcode ("cpl", "a");
3305 emitcode ("inc", "a");
3307 emitcode ("", "%05d$:", lbl->key+100);
3308 emitcode ("xch", "a,b");
3311 if (AOP_TYPE(right)==AOP_LIT) {
3312 /* AND literal negative */
3313 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3314 // two's complement for literal<0
3315 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3316 emitcode ("cpl", "a");
3317 emitcode ("inc", "a");
3320 lbl=newiTempLabel(NULL);
3321 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3322 // right side is negative, 8-bit two's complement
3323 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3324 emitcode ("cpl", "a");
3325 emitcode ("inc", "a");
3326 emitcode ("", "%05d$:", lbl->key+100);
3328 emitcode ("mul", "ab");
3330 lbl=newiTempLabel(NULL);
3331 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3332 // only ONE op was negative, we have to do a 8/16-bit two's complement
3333 emitcode ("cpl", "a"); // lsb
3335 emitcode ("inc", "a");
3337 emitcode ("add", "a,#1");
3338 emitcode ("xch", "a,b");
3339 emitcode ("cpl", "a"); // msb
3340 emitcode ("addc", "a,#0");
3341 emitcode ("xch", "a,b");
3344 emitcode ("", "%05d$:", lbl->key+100);
3345 aopPut (AOP (result), "a", 0);
3347 aopPut (AOP (result), "b", 1);
3352 /*-----------------------------------------------------------------*/
3353 /* genMult - generates code for multiplication */
3354 /*-----------------------------------------------------------------*/
3356 genMult (iCode * ic)
3358 operand *left = IC_LEFT (ic);
3359 operand *right = IC_RIGHT (ic);
3360 operand *result = IC_RESULT (ic);
3362 /* assign the amsops */
3363 aopOp (left, ic, FALSE);
3364 aopOp (right, ic, FALSE);
3365 aopOp (result, ic, TRUE);
3367 /* special cases first */
3369 if (AOP_TYPE (left) == AOP_CRY &&
3370 AOP_TYPE (right) == AOP_CRY)
3372 genMultbits (left, right, result);
3376 /* if both are of size == 1 */
3377 if (AOP_SIZE (left) == 1 &&
3378 AOP_SIZE (right) == 1)
3380 genMultOneByte (left, right, result);
3384 /* should have been converted to function call */
3388 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3389 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3390 freeAsmop (result, NULL, ic, TRUE);
3393 /*-----------------------------------------------------------------*/
3394 /* genDivbits :- division of bits */
3395 /*-----------------------------------------------------------------*/
3397 genDivbits (operand * left,
3404 /* the result must be bit */
3405 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3406 l = aopGet (AOP (left), 0, FALSE, FALSE);
3410 emitcode ("div", "ab");
3411 emitcode ("rrc", "a");
3412 aopPut (AOP (result), "c", 0);
3415 /*-----------------------------------------------------------------*/
3416 /* genDivOneByte : 8 bit division */
3417 /*-----------------------------------------------------------------*/
3419 genDivOneByte (operand * left,
3423 sym_link *opetype = operandType (result);
3428 size = AOP_SIZE (result) - 1;
3430 /* signed or unsigned */
3431 if (SPEC_USIGN (opetype))
3433 /* unsigned is easy */
3434 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3435 l = aopGet (AOP (left), 0, FALSE, FALSE);
3437 emitcode ("div", "ab");
3438 aopPut (AOP (result), "a", 0);
3440 aopPut (AOP (result), zero, offset++);
3444 /* signed is a little bit more difficult */
3446 /* save the signs of the operands */
3447 l = aopGet (AOP (left), 0, FALSE, FALSE);
3449 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3450 emitcode ("push", "acc"); /* save it on the stack */
3452 /* now sign adjust for both left & right */
3453 l = aopGet (AOP (right), 0, FALSE, FALSE);
3455 lbl = newiTempLabel (NULL);
3456 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3457 emitcode ("cpl", "a");
3458 emitcode ("inc", "a");
3459 emitcode ("", "%05d$:", (lbl->key + 100));
3460 emitcode ("mov", "b,a");
3462 /* sign adjust left side */
3463 l = aopGet (AOP (left), 0, FALSE, FALSE);
3466 lbl = newiTempLabel (NULL);
3467 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3468 emitcode ("cpl", "a");
3469 emitcode ("inc", "a");
3470 emitcode ("", "%05d$:", (lbl->key + 100));
3472 /* now the division */
3473 emitcode ("div", "ab");
3474 /* we are interested in the lower order
3476 emitcode ("mov", "b,a");
3477 lbl = newiTempLabel (NULL);
3478 emitcode ("pop", "acc");
3479 /* if there was an over flow we don't
3480 adjust the sign of the result */
3481 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3482 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3484 emitcode ("clr", "a");
3485 emitcode ("subb", "a,b");
3486 emitcode ("mov", "b,a");
3487 emitcode ("", "%05d$:", (lbl->key + 100));
3489 /* now we are done */
3490 aopPut (AOP (result), "b", 0);
3493 emitcode ("mov", "c,b.7");
3494 emitcode ("subb", "a,acc");
3497 aopPut (AOP (result), "a", offset++);
3501 /*-----------------------------------------------------------------*/
3502 /* genDiv - generates code for division */
3503 /*-----------------------------------------------------------------*/
3507 operand *left = IC_LEFT (ic);
3508 operand *right = IC_RIGHT (ic);
3509 operand *result = IC_RESULT (ic);
3511 /* assign the amsops */
3512 aopOp (left, ic, FALSE);
3513 aopOp (right, ic, FALSE);
3514 aopOp (result, ic, TRUE);
3516 /* special cases first */
3518 if (AOP_TYPE (left) == AOP_CRY &&
3519 AOP_TYPE (right) == AOP_CRY)
3521 genDivbits (left, right, result);
3525 /* if both are of size == 1 */
3526 if (AOP_SIZE (left) == 1 &&
3527 AOP_SIZE (right) == 1)
3529 genDivOneByte (left, right, result);
3533 /* should have been converted to function call */
3536 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3537 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3538 freeAsmop (result, NULL, ic, TRUE);
3541 /*-----------------------------------------------------------------*/
3542 /* genModbits :- modulus of bits */
3543 /*-----------------------------------------------------------------*/
3545 genModbits (operand * left,
3552 /* the result must be bit */
3553 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3554 l = aopGet (AOP (left), 0, FALSE, FALSE);
3558 emitcode ("div", "ab");
3559 emitcode ("mov", "a,b");
3560 emitcode ("rrc", "a");
3561 aopPut (AOP (result), "c", 0);
3564 /*-----------------------------------------------------------------*/
3565 /* genModOneByte : 8 bit modulus */
3566 /*-----------------------------------------------------------------*/
3568 genModOneByte (operand * left,
3572 sym_link *opetype = operandType (result);
3576 /* signed or unsigned */
3577 if (SPEC_USIGN (opetype))
3579 /* unsigned is easy */
3580 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3581 l = aopGet (AOP (left), 0, FALSE, FALSE);
3583 emitcode ("div", "ab");
3584 aopPut (AOP (result), "b", 0);
3588 /* signed is a little bit more difficult */
3590 /* save the signs of the operands */
3591 l = aopGet (AOP (left), 0, FALSE, FALSE);
3594 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3595 emitcode ("push", "acc"); /* save it on the stack */
3597 /* now sign adjust for both left & right */
3598 l = aopGet (AOP (right), 0, FALSE, FALSE);
3601 lbl = newiTempLabel (NULL);
3602 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3603 emitcode ("cpl", "a");
3604 emitcode ("inc", "a");
3605 emitcode ("", "%05d$:", (lbl->key + 100));
3606 emitcode ("mov", "b,a");
3608 /* sign adjust left side */
3609 l = aopGet (AOP (left), 0, FALSE, FALSE);
3612 lbl = newiTempLabel (NULL);
3613 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3614 emitcode ("cpl", "a");
3615 emitcode ("inc", "a");
3616 emitcode ("", "%05d$:", (lbl->key + 100));
3618 /* now the multiplication */
3619 emitcode ("div", "ab");
3620 /* we are interested in the lower order
3622 lbl = newiTempLabel (NULL);
3623 emitcode ("pop", "acc");
3624 /* if there was an over flow we don't
3625 adjust the sign of the result */
3626 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3627 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3629 emitcode ("clr", "a");
3630 emitcode ("subb", "a,b");
3631 emitcode ("mov", "b,a");
3632 emitcode ("", "%05d$:", (lbl->key + 100));
3634 /* now we are done */
3635 aopPut (AOP (result), "b", 0);
3639 /*-----------------------------------------------------------------*/
3640 /* genMod - generates code for division */
3641 /*-----------------------------------------------------------------*/
3645 operand *left = IC_LEFT (ic);
3646 operand *right = IC_RIGHT (ic);
3647 operand *result = IC_RESULT (ic);
3649 /* assign the amsops */
3650 aopOp (left, ic, FALSE);
3651 aopOp (right, ic, FALSE);
3652 aopOp (result, ic, TRUE);
3654 /* special cases first */
3656 if (AOP_TYPE (left) == AOP_CRY &&
3657 AOP_TYPE (right) == AOP_CRY)
3659 genModbits (left, right, result);
3663 /* if both are of size == 1 */
3664 if (AOP_SIZE (left) == 1 &&
3665 AOP_SIZE (right) == 1)
3667 genModOneByte (left, right, result);
3671 /* should have been converted to function call */
3675 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3677 freeAsmop (result, NULL, ic, TRUE);
3680 /*-----------------------------------------------------------------*/
3681 /* genIfxJump :- will create a jump depending on the ifx */
3682 /*-----------------------------------------------------------------*/
3684 genIfxJump (iCode * ic, char *jval)
3687 symbol *tlbl = newiTempLabel (NULL);
3690 /* if true label then we jump if condition
3694 jlbl = IC_TRUE (ic);
3695 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3696 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3700 /* false label is present */
3701 jlbl = IC_FALSE (ic);
3702 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3703 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3705 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3706 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3708 emitcode (inst, "%05d$", tlbl->key + 100);
3709 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3710 emitcode ("", "%05d$:", tlbl->key + 100);
3712 /* mark the icode as generated */
3716 /*-----------------------------------------------------------------*/
3717 /* genCmp :- greater or less than comparison */
3718 /*-----------------------------------------------------------------*/
3720 genCmp (operand * left, operand * right,
3721 operand * result, iCode * ifx, int sign)
3723 int size, offset = 0;
3724 unsigned long lit = 0L;
3726 /* if left & right are bit variables */
3727 if (AOP_TYPE (left) == AOP_CRY &&
3728 AOP_TYPE (right) == AOP_CRY)
3730 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3731 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3735 /* subtract right from left if at the
3736 end the carry flag is set then we know that
3737 left is greater than right */
3738 size = max (AOP_SIZE (left), AOP_SIZE (right));
3740 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3741 if ((size == 1) && !sign &&
3742 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3744 symbol *lbl = newiTempLabel (NULL);
3745 emitcode ("cjne", "%s,%s,%05d$",
3746 aopGet (AOP (left), offset, FALSE, FALSE),
3747 aopGet (AOP (right), offset, FALSE, FALSE),
3749 emitcode ("", "%05d$:", lbl->key + 100);
3753 if (AOP_TYPE (right) == AOP_LIT)
3755 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3756 /* optimize if(x < 0) or if(x >= 0) */
3765 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3766 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3768 genIfxJump (ifx, "acc.7");
3772 emitcode ("rlc", "a");
3780 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3781 if (sign && size == 0)
3783 emitcode ("xrl", "a,#0x80");
3784 if (AOP_TYPE (right) == AOP_LIT)
3786 unsigned long lit = (unsigned long)
3787 floatFromVal (AOP (right)->aopu.aop_lit);
3788 emitcode ("subb", "a,#0x%02x",
3789 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3793 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3794 emitcode ("xrl", "b,#0x80");
3795 emitcode ("subb", "a,b");
3799 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3805 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3811 /* if the result is used in the next
3812 ifx conditional branch then generate
3813 code a little differently */
3815 genIfxJump (ifx, "c");
3818 /* leave the result in acc */
3822 /*-----------------------------------------------------------------*/
3823 /* genCmpGt :- greater than comparison */
3824 /*-----------------------------------------------------------------*/
3826 genCmpGt (iCode * ic, iCode * ifx)
3828 operand *left, *right, *result;
3829 sym_link *letype, *retype;
3832 left = IC_LEFT (ic);
3833 right = IC_RIGHT (ic);
3834 result = IC_RESULT (ic);
3836 letype = getSpec (operandType (left));
3837 retype = getSpec (operandType (right));
3838 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3839 /* assign the amsops */
3840 aopOp (left, ic, FALSE);
3841 aopOp (right, ic, FALSE);
3842 aopOp (result, ic, TRUE);
3844 genCmp (right, left, result, ifx, sign);
3846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3848 freeAsmop (result, NULL, ic, TRUE);
3851 /*-----------------------------------------------------------------*/
3852 /* genCmpLt - less than comparisons */
3853 /*-----------------------------------------------------------------*/
3855 genCmpLt (iCode * ic, iCode * ifx)
3857 operand *left, *right, *result;
3858 sym_link *letype, *retype;
3861 left = IC_LEFT (ic);
3862 right = IC_RIGHT (ic);
3863 result = IC_RESULT (ic);
3865 letype = getSpec (operandType (left));
3866 retype = getSpec (operandType (right));
3867 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 (left, right, result, ifx, sign);
3876 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3877 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3878 freeAsmop (result, NULL, ic, TRUE);
3881 /*-----------------------------------------------------------------*/
3882 /* gencjneshort - compare and jump if not equal */
3883 /*-----------------------------------------------------------------*/
3885 gencjneshort (operand * left, operand * right, symbol * lbl)
3887 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3889 unsigned long lit = 0L;
3891 /* if the left side is a literal or
3892 if the right is in a pointer register and left
3894 if ((AOP_TYPE (left) == AOP_LIT) ||
3895 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3901 if (AOP_TYPE (right) == AOP_LIT)
3902 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3904 /* if the right side is a literal then anything goes */
3905 if (AOP_TYPE (right) == AOP_LIT &&
3906 AOP_TYPE (left) != AOP_DIR)
3910 emitcode ("cjne", "%s,%s,%05d$",
3911 aopGet (AOP (left), offset, FALSE, FALSE),
3912 aopGet (AOP (right), offset, FALSE, FALSE),
3918 /* if the right side is in a register or in direct space or
3919 if the left is a pointer register & right is not */
3920 else if (AOP_TYPE (right) == AOP_REG ||
3921 AOP_TYPE (right) == AOP_DIR ||
3922 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3923 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3927 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3928 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3929 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3930 emitcode ("jnz", "%05d$", lbl->key + 100);
3932 emitcode ("cjne", "a,%s,%05d$",
3933 aopGet (AOP (right), offset, FALSE, TRUE),
3940 /* right is a pointer reg need both a & b */
3943 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3944 if (strcmp (l, "b"))
3945 emitcode ("mov", "b,%s", l);
3946 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3947 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3953 /*-----------------------------------------------------------------*/
3954 /* gencjne - compare and jump if not equal */
3955 /*-----------------------------------------------------------------*/
3957 gencjne (operand * left, operand * right, symbol * lbl)
3959 symbol *tlbl = newiTempLabel (NULL);
3961 gencjneshort (left, right, lbl);
3963 emitcode ("mov", "a,%s", one);
3964 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3965 emitcode ("", "%05d$:", lbl->key + 100);
3966 emitcode ("clr", "a");
3967 emitcode ("", "%05d$:", tlbl->key + 100);
3970 /*-----------------------------------------------------------------*/
3971 /* genCmpEq - generates code for equal to */
3972 /*-----------------------------------------------------------------*/
3974 genCmpEq (iCode * ic, iCode * ifx)
3976 operand *left, *right, *result;
3978 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3979 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3980 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3982 /* if literal, literal on the right or
3983 if the right is in a pointer register and left
3985 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3986 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3988 operand *t = IC_RIGHT (ic);
3989 IC_RIGHT (ic) = IC_LEFT (ic);
3993 if (ifx && !AOP_SIZE (result))
3996 /* if they are both bit variables */
3997 if (AOP_TYPE (left) == AOP_CRY &&
3998 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4000 if (AOP_TYPE (right) == AOP_LIT)
4002 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4005 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4006 emitcode ("cpl", "c");
4010 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4014 emitcode ("clr", "c");
4016 /* AOP_TYPE(right) == AOP_CRY */
4020 symbol *lbl = newiTempLabel (NULL);
4021 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4022 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4023 emitcode ("cpl", "c");
4024 emitcode ("", "%05d$:", (lbl->key + 100));
4026 /* if true label then we jump if condition
4028 tlbl = newiTempLabel (NULL);
4031 emitcode ("jnc", "%05d$", tlbl->key + 100);
4032 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4036 emitcode ("jc", "%05d$", tlbl->key + 100);
4037 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4039 emitcode ("", "%05d$:", tlbl->key + 100);
4043 tlbl = newiTempLabel (NULL);
4044 gencjneshort (left, right, tlbl);
4047 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4048 emitcode ("", "%05d$:", tlbl->key + 100);
4052 symbol *lbl = newiTempLabel (NULL);
4053 emitcode ("sjmp", "%05d$", lbl->key + 100);
4054 emitcode ("", "%05d$:", tlbl->key + 100);
4055 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4056 emitcode ("", "%05d$:", lbl->key + 100);
4059 /* mark the icode as generated */
4064 /* if they are both bit variables */
4065 if (AOP_TYPE (left) == AOP_CRY &&
4066 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4068 if (AOP_TYPE (right) == AOP_LIT)
4070 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4073 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4074 emitcode ("cpl", "c");
4078 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4082 emitcode ("clr", "c");
4084 /* AOP_TYPE(right) == AOP_CRY */
4088 symbol *lbl = newiTempLabel (NULL);
4089 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4090 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4091 emitcode ("cpl", "c");
4092 emitcode ("", "%05d$:", (lbl->key + 100));
4095 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4102 genIfxJump (ifx, "c");
4105 /* if the result is used in an arithmetic operation
4106 then put the result in place */
4111 gencjne (left, right, newiTempLabel (NULL));
4112 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4114 aopPut (AOP (result), "a", 0);
4119 genIfxJump (ifx, "a");
4122 /* if the result is used in an arithmetic operation
4123 then put the result in place */
4124 if (AOP_TYPE (result) != AOP_CRY)
4126 /* leave the result in acc */
4130 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4131 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4132 freeAsmop (result, NULL, ic, TRUE);
4135 /*-----------------------------------------------------------------*/
4136 /* ifxForOp - returns the icode containing the ifx for operand */
4137 /*-----------------------------------------------------------------*/
4139 ifxForOp (operand * op, iCode * ic)
4141 /* if true symbol then needs to be assigned */
4142 if (IS_TRUE_SYMOP (op))
4145 /* if this has register type condition and
4146 the next instruction is ifx with the same operand
4147 and live to of the operand is upto the ifx only then */
4149 ic->next->op == IFX &&
4150 IC_COND (ic->next)->key == op->key &&
4151 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4156 /*-----------------------------------------------------------------*/
4157 /* genAndOp - for && operation */
4158 /*-----------------------------------------------------------------*/
4160 genAndOp (iCode * ic)
4162 operand *left, *right, *result;
4165 /* note here that && operations that are in an
4166 if statement are taken away by backPatchLabels
4167 only those used in arthmetic operations remain */
4168 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4169 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4170 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4172 /* if both are bit variables */
4173 if (AOP_TYPE (left) == AOP_CRY &&
4174 AOP_TYPE (right) == AOP_CRY)
4176 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4177 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4182 tlbl = newiTempLabel (NULL);
4184 emitcode ("jz", "%05d$", tlbl->key + 100);
4186 emitcode ("", "%05d$:", tlbl->key + 100);
4190 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192 freeAsmop (result, NULL, ic, TRUE);
4196 /*-----------------------------------------------------------------*/
4197 /* genOrOp - for || operation */
4198 /*-----------------------------------------------------------------*/
4200 genOrOp (iCode * ic)
4202 operand *left, *right, *result;
4205 /* note here that || operations that are in an
4206 if statement are taken away by backPatchLabels
4207 only those used in arthmetic operations remain */
4208 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4209 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4210 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4212 /* if both are bit variables */
4213 if (AOP_TYPE (left) == AOP_CRY &&
4214 AOP_TYPE (right) == AOP_CRY)
4216 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4217 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4222 tlbl = newiTempLabel (NULL);
4224 emitcode ("jnz", "%05d$", tlbl->key + 100);
4226 emitcode ("", "%05d$:", tlbl->key + 100);
4230 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4231 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4232 freeAsmop (result, NULL, ic, TRUE);
4235 /*-----------------------------------------------------------------*/
4236 /* isLiteralBit - test if lit == 2^n */
4237 /*-----------------------------------------------------------------*/
4239 isLiteralBit (unsigned long lit)
4241 unsigned long pw[32] =
4242 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4243 0x100L, 0x200L, 0x400L, 0x800L,
4244 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4245 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4246 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4247 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4248 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4251 for (idx = 0; idx < 32; idx++)
4257 /*-----------------------------------------------------------------*/
4258 /* continueIfTrue - */
4259 /*-----------------------------------------------------------------*/
4261 continueIfTrue (iCode * ic)
4264 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4268 /*-----------------------------------------------------------------*/
4270 /*-----------------------------------------------------------------*/
4272 jumpIfTrue (iCode * ic)
4275 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4279 /*-----------------------------------------------------------------*/
4280 /* jmpTrueOrFalse - */
4281 /*-----------------------------------------------------------------*/
4283 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4285 // ugly but optimized by peephole
4288 symbol *nlbl = newiTempLabel (NULL);
4289 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4290 emitcode ("", "%05d$:", tlbl->key + 100);
4291 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4292 emitcode ("", "%05d$:", nlbl->key + 100);
4296 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4297 emitcode ("", "%05d$:", tlbl->key + 100);
4302 /*-----------------------------------------------------------------*/
4303 /* genAnd - code for and */
4304 /*-----------------------------------------------------------------*/
4306 genAnd (iCode * ic, iCode * ifx)
4308 operand *left, *right, *result;
4309 int size, offset = 0;
4310 unsigned long lit = 0L;
4314 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4315 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4316 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4319 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4321 AOP_TYPE (left), AOP_TYPE (right));
4322 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4324 AOP_SIZE (left), AOP_SIZE (right));
4327 /* if left is a literal & right is not then exchange them */
4328 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4329 AOP_NEEDSACC (left))
4331 operand *tmp = right;
4336 /* if result = right then exchange them */
4337 if (sameRegs (AOP (result), AOP (right)))
4339 operand *tmp = right;
4344 /* if right is bit then exchange them */
4345 if (AOP_TYPE (right) == AOP_CRY &&
4346 AOP_TYPE (left) != AOP_CRY)
4348 operand *tmp = right;
4352 if (AOP_TYPE (right) == AOP_LIT)
4353 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4355 size = AOP_SIZE (result);
4358 // result = bit & yy;
4359 if (AOP_TYPE (left) == AOP_CRY)
4361 // c = bit & literal;
4362 if (AOP_TYPE (right) == AOP_LIT)
4366 if (size && sameRegs (AOP (result), AOP (left)))
4369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4374 if (size && (AOP_TYPE (result) == AOP_CRY))
4376 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4379 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4384 emitcode ("clr", "c");
4389 if (AOP_TYPE (right) == AOP_CRY)
4392 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4393 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4398 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4400 emitcode ("rrc", "a");
4401 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4409 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4410 genIfxJump (ifx, "c");
4414 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4415 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4416 if ((AOP_TYPE (right) == AOP_LIT) &&
4417 (AOP_TYPE (result) == AOP_CRY) &&
4418 (AOP_TYPE (left) != AOP_CRY))
4420 int posbit = isLiteralBit (lit);
4425 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4428 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4434 sprintf (buffer, "acc.%d", posbit & 0x07);
4435 genIfxJump (ifx, buffer);
4442 symbol *tlbl = newiTempLabel (NULL);
4443 int sizel = AOP_SIZE (left);
4445 emitcode ("setb", "c");
4448 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4450 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4452 if ((posbit = isLiteralBit (bytelit)) != 0)
4453 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4456 if (bytelit != 0x0FFL)
4457 emitcode ("anl", "a,%s",
4458 aopGet (AOP (right), offset, FALSE, TRUE));
4459 emitcode ("jnz", "%05d$", tlbl->key + 100);
4464 // bit = left & literal
4467 emitcode ("clr", "c");
4468 emitcode ("", "%05d$:", tlbl->key + 100);
4470 // if(left & literal)
4474 jmpTrueOrFalse (ifx, tlbl);
4482 /* if left is same as result */
4483 if (sameRegs (AOP (result), AOP (left)))
4485 for (; size--; offset++)
4487 if (AOP_TYPE (right) == AOP_LIT)
4489 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4491 else if (bytelit == 0)
4492 aopPut (AOP (result), zero, offset);
4493 else if (IS_AOP_PREG (result))
4495 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4496 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4497 aopPut (AOP (result), "a", offset);
4500 emitcode ("anl", "%s,%s",
4501 aopGet (AOP (left), offset, FALSE, TRUE),
4502 aopGet (AOP (right), offset, FALSE, FALSE));
4506 if (AOP_TYPE (left) == AOP_ACC)
4507 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4510 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4511 if (IS_AOP_PREG (result))
4513 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4514 aopPut (AOP (result), "a", offset);
4518 emitcode ("anl", "%s,a",
4519 aopGet (AOP (left), offset, FALSE, TRUE));
4526 // left & result in different registers
4527 if (AOP_TYPE (result) == AOP_CRY)
4530 // if(size), result in bit
4531 // if(!size && ifx), conditional oper: if(left & right)
4532 symbol *tlbl = newiTempLabel (NULL);
4533 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4535 emitcode ("setb", "c");
4538 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4539 emitcode ("anl", "a,%s",
4540 aopGet (AOP (left), offset, FALSE, FALSE));
4541 emitcode ("jnz", "%05d$", tlbl->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4551 jmpTrueOrFalse (ifx, tlbl);
4555 for (; (size--); offset++)
4558 // result = left & right
4559 if (AOP_TYPE (right) == AOP_LIT)
4561 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4563 aopPut (AOP (result),
4564 aopGet (AOP (left), offset, FALSE, FALSE),
4568 else if (bytelit == 0)
4570 aopPut (AOP (result), zero, offset);
4574 // faster than result <- left, anl result,right
4575 // and better if result is SFR
4576 if (AOP_TYPE (left) == AOP_ACC)
4577 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4580 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4581 emitcode ("anl", "a,%s",
4582 aopGet (AOP (left), offset, FALSE, FALSE));
4584 aopPut (AOP (result), "a", offset);
4590 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4591 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4592 freeAsmop (result, NULL, ic, TRUE);
4595 /*-----------------------------------------------------------------*/
4596 /* genOr - code for or */
4597 /*-----------------------------------------------------------------*/
4599 genOr (iCode * ic, iCode * ifx)
4601 operand *left, *right, *result;
4602 int size, offset = 0;
4603 unsigned long lit = 0L;
4605 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4606 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4607 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4610 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4612 AOP_TYPE (left), AOP_TYPE (right));
4613 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4615 AOP_SIZE (left), AOP_SIZE (right));
4618 /* if left is a literal & right is not then exchange them */
4619 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4620 AOP_NEEDSACC (left))
4622 operand *tmp = right;
4627 /* if result = right then exchange them */
4628 if (sameRegs (AOP (result), AOP (right)))
4630 operand *tmp = right;
4635 /* if right is bit then exchange them */
4636 if (AOP_TYPE (right) == AOP_CRY &&
4637 AOP_TYPE (left) != AOP_CRY)
4639 operand *tmp = right;
4643 if (AOP_TYPE (right) == AOP_LIT)
4644 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4646 size = AOP_SIZE (result);
4650 if (AOP_TYPE (left) == AOP_CRY)
4652 if (AOP_TYPE (right) == AOP_LIT)
4654 // c = bit & literal;
4657 // lit != 0 => result = 1
4658 if (AOP_TYPE (result) == AOP_CRY)
4661 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4663 continueIfTrue (ifx);
4666 emitcode ("setb", "c");
4670 // lit == 0 => result = left
4671 if (size && sameRegs (AOP (result), AOP (left)))
4673 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4678 if (AOP_TYPE (right) == AOP_CRY)
4681 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4682 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4687 symbol *tlbl = newiTempLabel (NULL);
4688 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4689 emitcode ("setb", "c");
4690 emitcode ("jb", "%s,%05d$",
4691 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4693 emitcode ("jnz", "%05d$", tlbl->key + 100);
4694 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4696 jmpTrueOrFalse (ifx, tlbl);
4702 emitcode ("", "%05d$:", tlbl->key + 100);
4711 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4712 genIfxJump (ifx, "c");
4716 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4717 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4718 if ((AOP_TYPE (right) == AOP_LIT) &&
4719 (AOP_TYPE (result) == AOP_CRY) &&
4720 (AOP_TYPE (left) != AOP_CRY))
4726 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4728 continueIfTrue (ifx);
4733 // lit = 0, result = boolean(left)
4735 emitcode ("setb", "c");
4739 symbol *tlbl = newiTempLabel (NULL);
4740 emitcode ("jnz", "%05d$", tlbl->key + 100);
4742 emitcode ("", "%05d$:", tlbl->key + 100);
4746 genIfxJump (ifx, "a");
4754 /* if left is same as result */
4755 if (sameRegs (AOP (result), AOP (left)))
4757 for (; size--; offset++)
4759 if (AOP_TYPE (right) == AOP_LIT)
4761 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4763 else if (IS_AOP_PREG (left))
4765 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4766 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4767 aopPut (AOP (result), "a", offset);
4770 emitcode ("orl", "%s,%s",
4771 aopGet (AOP (left), offset, FALSE, TRUE),
4772 aopGet (AOP (right), offset, FALSE, FALSE));
4776 if (AOP_TYPE (left) == AOP_ACC)
4777 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4780 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4781 if (IS_AOP_PREG (left))
4783 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4784 aopPut (AOP (result), "a", offset);
4787 emitcode ("orl", "%s,a",
4788 aopGet (AOP (left), offset, FALSE, TRUE));
4795 // left & result in different registers
4796 if (AOP_TYPE (result) == AOP_CRY)
4799 // if(size), result in bit
4800 // if(!size && ifx), conditional oper: if(left | right)
4801 symbol *tlbl = newiTempLabel (NULL);
4802 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4804 emitcode ("setb", "c");
4807 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4808 emitcode ("orl", "a,%s",
4809 aopGet (AOP (left), offset, FALSE, FALSE));
4810 emitcode ("jnz", "%05d$", tlbl->key + 100);
4816 emitcode ("", "%05d$:", tlbl->key + 100);
4820 jmpTrueOrFalse (ifx, tlbl);
4823 for (; (size--); offset++)
4826 // result = left & right
4827 if (AOP_TYPE (right) == AOP_LIT)
4829 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4831 aopPut (AOP (result),
4832 aopGet (AOP (left), offset, FALSE, FALSE),
4837 // faster than result <- left, anl result,right
4838 // and better if result is SFR
4839 if (AOP_TYPE (left) == AOP_ACC)
4840 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4843 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4844 emitcode ("orl", "a,%s",
4845 aopGet (AOP (left), offset, FALSE, FALSE));
4847 aopPut (AOP (result), "a", offset);
4852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854 freeAsmop (result, NULL, ic, TRUE);
4857 /*-----------------------------------------------------------------*/
4858 /* genXor - code for xclusive or */
4859 /*-----------------------------------------------------------------*/
4861 genXor (iCode * ic, iCode * ifx)
4863 operand *left, *right, *result;
4864 int size, offset = 0;
4865 unsigned long lit = 0L;
4867 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4868 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4869 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4872 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4874 AOP_TYPE (left), AOP_TYPE (right));
4875 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4877 AOP_SIZE (left), AOP_SIZE (right));
4880 /* if left is a literal & right is not ||
4881 if left needs acc & right does not */
4882 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4883 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4885 operand *tmp = right;
4890 /* if result = right then exchange them */
4891 if (sameRegs (AOP (result), AOP (right)))
4893 operand *tmp = right;
4898 /* if right is bit then exchange them */
4899 if (AOP_TYPE (right) == AOP_CRY &&
4900 AOP_TYPE (left) != AOP_CRY)
4902 operand *tmp = right;
4906 if (AOP_TYPE (right) == AOP_LIT)
4907 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4909 size = AOP_SIZE (result);
4913 if (AOP_TYPE (left) == AOP_CRY)
4915 if (AOP_TYPE (right) == AOP_LIT)
4917 // c = bit & literal;
4920 // lit>>1 != 0 => result = 1
4921 if (AOP_TYPE (result) == AOP_CRY)
4924 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4926 continueIfTrue (ifx);
4929 emitcode ("setb", "c");
4936 // lit == 0, result = left
4937 if (size && sameRegs (AOP (result), AOP (left)))
4939 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4943 // lit == 1, result = not(left)
4944 if (size && sameRegs (AOP (result), AOP (left)))
4946 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4952 emitcode ("cpl", "c");
4961 symbol *tlbl = newiTempLabel (NULL);
4962 if (AOP_TYPE (right) == AOP_CRY)
4965 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4969 int sizer = AOP_SIZE (right);
4971 // if val>>1 != 0, result = 1
4972 emitcode ("setb", "c");
4975 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4977 // test the msb of the lsb
4978 emitcode ("anl", "a,#0xfe");
4979 emitcode ("jnz", "%05d$", tlbl->key + 100);
4983 emitcode ("rrc", "a");
4985 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4986 emitcode ("cpl", "c");
4987 emitcode ("", "%05d$:", (tlbl->key + 100));
4994 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4995 genIfxJump (ifx, "c");
4999 if (sameRegs (AOP (result), AOP (left)))
5001 /* if left is same as result */
5002 for (; size--; offset++)
5004 if (AOP_TYPE (right) == AOP_LIT)
5006 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5008 else if (IS_AOP_PREG (left))
5010 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5011 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5012 aopPut (AOP (result), "a", offset);
5015 emitcode ("xrl", "%s,%s",
5016 aopGet (AOP (left), offset, FALSE, TRUE),
5017 aopGet (AOP (right), offset, FALSE, FALSE));
5021 if (AOP_TYPE (left) == AOP_ACC)
5022 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5025 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5026 if (IS_AOP_PREG (left))
5028 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5029 aopPut (AOP (result), "a", offset);
5032 emitcode ("xrl", "%s,a",
5033 aopGet (AOP (left), offset, FALSE, TRUE));
5040 // left & result in different registers
5041 if (AOP_TYPE (result) == AOP_CRY)
5044 // if(size), result in bit
5045 // if(!size && ifx), conditional oper: if(left ^ right)
5046 symbol *tlbl = newiTempLabel (NULL);
5047 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5049 emitcode ("setb", "c");
5052 if ((AOP_TYPE (right) == AOP_LIT) &&
5053 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5055 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5059 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5060 emitcode ("xrl", "a,%s",
5061 aopGet (AOP (left), offset, FALSE, FALSE));
5063 emitcode ("jnz", "%05d$", tlbl->key + 100);
5069 emitcode ("", "%05d$:", tlbl->key + 100);
5073 jmpTrueOrFalse (ifx, tlbl);
5076 for (; (size--); offset++)
5079 // result = left & right
5080 if (AOP_TYPE (right) == AOP_LIT)
5082 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5084 aopPut (AOP (result),
5085 aopGet (AOP (left), offset, FALSE, FALSE),
5090 // faster than result <- left, anl result,right
5091 // and better if result is SFR
5092 if (AOP_TYPE (left) == AOP_ACC)
5093 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5096 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5097 emitcode ("xrl", "a,%s",
5098 aopGet (AOP (left), offset, FALSE, TRUE));
5100 aopPut (AOP (result), "a", offset);
5105 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5106 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5107 freeAsmop (result, NULL, ic, TRUE);
5110 /*-----------------------------------------------------------------*/
5111 /* genInline - write the inline code out */
5112 /*-----------------------------------------------------------------*/
5114 genInline (iCode * ic)
5116 char buffer[MAX_INLINEASM];
5120 _G.inLine += (!options.asmpeep);
5121 strcpy (buffer, IC_INLINE (ic));
5123 /* emit each line as a code */
5148 /* emitcode("",buffer); */
5149 _G.inLine -= (!options.asmpeep);
5152 /*-----------------------------------------------------------------*/
5153 /* genRRC - rotate right with carry */
5154 /*-----------------------------------------------------------------*/
5158 operand *left, *result;
5159 int size, offset = 0;
5162 /* rotate right with carry */
5163 left = IC_LEFT (ic);
5164 result = IC_RESULT (ic);
5165 aopOp (left, ic, FALSE);
5166 aopOp (result, ic, FALSE);
5168 /* move it to the result */
5169 size = AOP_SIZE (result);
5174 l = aopGet (AOP (left), offset, FALSE, FALSE);
5176 emitcode ("rrc", "a");
5177 if (AOP_SIZE (result) > 1)
5178 aopPut (AOP (result), "a", offset--);
5180 /* now we need to put the carry into the
5181 highest order byte of the result */
5182 if (AOP_SIZE (result) > 1)
5184 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5187 emitcode ("mov", "acc.7,c");
5188 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5189 freeAsmop (left, NULL, ic, TRUE);
5190 freeAsmop (result, NULL, ic, TRUE);
5193 /*-----------------------------------------------------------------*/
5194 /* genRLC - generate code for rotate left with carry */
5195 /*-----------------------------------------------------------------*/
5199 operand *left, *result;
5200 int size, offset = 0;
5203 /* rotate right with carry */
5204 left = IC_LEFT (ic);
5205 result = IC_RESULT (ic);
5206 aopOp (left, ic, FALSE);
5207 aopOp (result, ic, FALSE);
5209 /* move it to the result */
5210 size = AOP_SIZE (result);
5214 l = aopGet (AOP (left), offset, FALSE, FALSE);
5216 emitcode ("add", "a,acc");
5217 if (AOP_SIZE (result) > 1)
5218 aopPut (AOP (result), "a", offset++);
5221 l = aopGet (AOP (left), offset, FALSE, FALSE);
5223 emitcode ("rlc", "a");
5224 if (AOP_SIZE (result) > 1)
5225 aopPut (AOP (result), "a", offset++);
5228 /* now we need to put the carry into the
5229 highest order byte of the result */
5230 if (AOP_SIZE (result) > 1)
5232 l = aopGet (AOP (result), 0, FALSE, FALSE);
5235 emitcode ("mov", "acc.0,c");
5236 aopPut (AOP (result), "a", 0);
5237 freeAsmop (left, NULL, ic, TRUE);
5238 freeAsmop (result, NULL, ic, TRUE);
5241 /*-----------------------------------------------------------------*/
5242 /* genGetHbit - generates code get highest order bit */
5243 /*-----------------------------------------------------------------*/
5245 genGetHbit (iCode * ic)
5247 operand *left, *result;
5248 left = IC_LEFT (ic);
5249 result = IC_RESULT (ic);
5250 aopOp (left, ic, FALSE);
5251 aopOp (result, ic, FALSE);
5253 /* get the highest order byte into a */
5254 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5255 if (AOP_TYPE (result) == AOP_CRY)
5257 emitcode ("rlc", "a");
5262 emitcode ("rl", "a");
5263 emitcode ("anl", "a,#0x01");
5268 freeAsmop (left, NULL, ic, TRUE);
5269 freeAsmop (result, NULL, ic, TRUE);
5272 /*-----------------------------------------------------------------*/
5273 /* AccRol - rotate left accumulator by known count */
5274 /*-----------------------------------------------------------------*/
5276 AccRol (int shCount)
5278 shCount &= 0x0007; // shCount : 0..7
5285 emitcode ("rl", "a");
5288 emitcode ("rl", "a");
5289 emitcode ("rl", "a");
5292 emitcode ("swap", "a");
5293 emitcode ("rr", "a");
5296 emitcode ("swap", "a");
5299 emitcode ("swap", "a");
5300 emitcode ("rl", "a");
5303 emitcode ("rr", "a");
5304 emitcode ("rr", "a");
5307 emitcode ("rr", "a");
5312 /*-----------------------------------------------------------------*/
5313 /* AccLsh - left shift accumulator by known count */
5314 /*-----------------------------------------------------------------*/
5316 AccLsh (int shCount)
5321 emitcode ("add", "a,acc");
5322 else if (shCount == 2)
5324 emitcode ("add", "a,acc");
5325 emitcode ("add", "a,acc");
5329 /* rotate left accumulator */
5331 /* and kill the lower order bits */
5332 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5337 /*-----------------------------------------------------------------*/
5338 /* AccRsh - right shift accumulator by known count */
5339 /*-----------------------------------------------------------------*/
5341 AccRsh (int shCount)
5348 emitcode ("rrc", "a");
5352 /* rotate right accumulator */
5353 AccRol (8 - shCount);
5354 /* and kill the higher order bits */
5355 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5360 /*-----------------------------------------------------------------*/
5361 /* AccSRsh - signed right shift accumulator by known count */
5362 /*-----------------------------------------------------------------*/
5364 AccSRsh (int shCount)
5371 emitcode ("mov", "c,acc.7");
5372 emitcode ("rrc", "a");
5374 else if (shCount == 2)
5376 emitcode ("mov", "c,acc.7");
5377 emitcode ("rrc", "a");
5378 emitcode ("mov", "c,acc.7");
5379 emitcode ("rrc", "a");
5383 tlbl = newiTempLabel (NULL);
5384 /* rotate right accumulator */
5385 AccRol (8 - shCount);
5386 /* and kill the higher order bits */
5387 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5388 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5389 emitcode ("orl", "a,#0x%02x",
5390 (unsigned char) ~SRMask[shCount]);
5391 emitcode ("", "%05d$:", tlbl->key + 100);
5396 /*-----------------------------------------------------------------*/
5397 /* shiftR1Left2Result - shift right one byte from left to result */
5398 /*-----------------------------------------------------------------*/
5400 shiftR1Left2Result (operand * left, int offl,
5401 operand * result, int offr,
5402 int shCount, int sign)
5404 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5405 /* shift right accumulator */
5410 aopPut (AOP (result), "a", offr);
5413 /*-----------------------------------------------------------------*/
5414 /* shiftL1Left2Result - shift left one byte from left to result */
5415 /*-----------------------------------------------------------------*/
5417 shiftL1Left2Result (operand * left, int offl,
5418 operand * result, int offr, int shCount)
5421 l = aopGet (AOP (left), offl, FALSE, FALSE);
5423 /* shift left accumulator */
5425 aopPut (AOP (result), "a", offr);
5428 /*-----------------------------------------------------------------*/
5429 /* movLeft2Result - move byte from left to result */
5430 /*-----------------------------------------------------------------*/
5432 movLeft2Result (operand * left, int offl,
5433 operand * result, int offr, int sign)
5436 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5438 l = aopGet (AOP (left), offl, FALSE, FALSE);
5440 if (*l == '@' && (IS_AOP_PREG (result)))
5442 emitcode ("mov", "a,%s", l);
5443 aopPut (AOP (result), "a", offr);
5448 aopPut (AOP (result), l, offr);
5451 /* MSB sign in acc.7 ! */
5452 if (getDataSize (left) == offl + 1)
5454 emitcode ("mov", "a,%s", l);
5455 aopPut (AOP (result), "a", offr);
5462 /*-----------------------------------------------------------------*/
5463 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5464 /*-----------------------------------------------------------------*/
5468 emitcode ("rrc", "a");
5469 emitcode ("xch", "a,%s", x);
5470 emitcode ("rrc", "a");
5471 emitcode ("xch", "a,%s", x);
5474 /*-----------------------------------------------------------------*/
5475 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5476 /*-----------------------------------------------------------------*/
5480 emitcode ("xch", "a,%s", x);
5481 emitcode ("rlc", "a");
5482 emitcode ("xch", "a,%s", x);
5483 emitcode ("rlc", "a");
5486 /*-----------------------------------------------------------------*/
5487 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5488 /*-----------------------------------------------------------------*/
5492 emitcode ("xch", "a,%s", x);
5493 emitcode ("add", "a,acc");
5494 emitcode ("xch", "a,%s", x);
5495 emitcode ("rlc", "a");
5498 /*-----------------------------------------------------------------*/
5499 /* AccAXLsh - left shift a:x by known count (0..7) */
5500 /*-----------------------------------------------------------------*/
5502 AccAXLsh (char *x, int shCount)
5517 case 5: // AAAAABBB:CCCCCDDD
5519 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5521 emitcode ("anl", "a,#0x%02x",
5522 SLMask[shCount]); // BBB00000:CCCCCDDD
5524 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5526 AccRol (shCount); // DDDCCCCC:BBB00000
5528 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5530 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5532 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5534 emitcode ("anl", "a,#0x%02x",
5535 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5537 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5539 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5542 case 6: // AAAAAABB:CCCCCCDD
5543 emitcode ("anl", "a,#0x%02x",
5544 SRMask[shCount]); // 000000BB:CCCCCCDD
5545 emitcode ("mov", "c,acc.0"); // c = B
5546 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5548 AccAXRrl1 (x); // BCCCCCCD:D000000B
5549 AccAXRrl1 (x); // BBCCCCCC:DD000000
5551 emitcode("rrc","a");
5552 emitcode("xch","a,%s", x);
5553 emitcode("rrc","a");
5554 emitcode("mov","c,acc.0"); //<< get correct bit
5555 emitcode("xch","a,%s", x);
5557 emitcode("rrc","a");
5558 emitcode("xch","a,%s", x);
5559 emitcode("rrc","a");
5560 emitcode("xch","a,%s", x);
5563 case 7: // a:x <<= 7
5565 emitcode ("anl", "a,#0x%02x",
5566 SRMask[shCount]); // 0000000B:CCCCCCCD
5568 emitcode ("mov", "c,acc.0"); // c = B
5570 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5572 AccAXRrl1 (x); // BCCCCCCC:D0000000
5580 /*-----------------------------------------------------------------*/
5581 /* AccAXRsh - right shift a:x known count (0..7) */
5582 /*-----------------------------------------------------------------*/
5584 AccAXRsh (char *x, int shCount)
5592 AccAXRrl1 (x); // 0->a:x
5597 AccAXRrl1 (x); // 0->a:x
5600 AccAXRrl1 (x); // 0->a:x
5605 case 5: // AAAAABBB:CCCCCDDD = a:x
5607 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5609 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5611 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5613 emitcode ("anl", "a,#0x%02x",
5614 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5616 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5618 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5620 emitcode ("anl", "a,#0x%02x",
5621 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5623 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5625 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5627 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5630 case 6: // AABBBBBB:CCDDDDDD
5632 emitcode ("mov", "c,acc.7");
5633 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5635 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5637 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5639 emitcode ("anl", "a,#0x%02x",
5640 SRMask[shCount]); // 000000AA:BBBBBBCC
5643 case 7: // ABBBBBBB:CDDDDDDD
5645 emitcode ("mov", "c,acc.7"); // c = A
5647 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5649 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5651 emitcode ("anl", "a,#0x%02x",
5652 SRMask[shCount]); // 0000000A:BBBBBBBC
5660 /*-----------------------------------------------------------------*/
5661 /* AccAXRshS - right shift signed a:x known count (0..7) */
5662 /*-----------------------------------------------------------------*/
5664 AccAXRshS (char *x, int shCount)
5672 emitcode ("mov", "c,acc.7");
5673 AccAXRrl1 (x); // s->a:x
5677 emitcode ("mov", "c,acc.7");
5678 AccAXRrl1 (x); // s->a:x
5680 emitcode ("mov", "c,acc.7");
5681 AccAXRrl1 (x); // s->a:x
5686 case 5: // AAAAABBB:CCCCCDDD = a:x
5688 tlbl = newiTempLabel (NULL);
5689 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5691 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5693 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5695 emitcode ("anl", "a,#0x%02x",
5696 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5698 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5700 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5702 emitcode ("anl", "a,#0x%02x",
5703 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5705 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5707 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5709 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5711 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5712 emitcode ("orl", "a,#0x%02x",
5713 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5715 emitcode ("", "%05d$:", tlbl->key + 100);
5716 break; // SSSSAAAA:BBBCCCCC
5718 case 6: // AABBBBBB:CCDDDDDD
5720 tlbl = newiTempLabel (NULL);
5721 emitcode ("mov", "c,acc.7");
5722 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5724 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5726 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5728 emitcode ("anl", "a,#0x%02x",
5729 SRMask[shCount]); // 000000AA:BBBBBBCC
5731 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5732 emitcode ("orl", "a,#0x%02x",
5733 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5735 emitcode ("", "%05d$:", tlbl->key + 100);
5737 case 7: // ABBBBBBB:CDDDDDDD
5739 tlbl = newiTempLabel (NULL);
5740 emitcode ("mov", "c,acc.7"); // c = A
5742 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5744 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5746 emitcode ("anl", "a,#0x%02x",
5747 SRMask[shCount]); // 0000000A:BBBBBBBC
5749 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5750 emitcode ("orl", "a,#0x%02x",
5751 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5753 emitcode ("", "%05d$:", tlbl->key + 100);
5760 /*-----------------------------------------------------------------*/
5761 /* shiftL2Left2Result - shift left two bytes from left to result */
5762 /*-----------------------------------------------------------------*/
5764 shiftL2Left2Result (operand * left, int offl,
5765 operand * result, int offr, int shCount)
5767 if (sameRegs (AOP (result), AOP (left)) &&
5768 ((offl + MSB16) == offr))
5770 /* don't crash result[offr] */
5771 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5772 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5776 movLeft2Result (left, offl, result, offr, 0);
5777 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5779 /* ax << shCount (x = lsb(result)) */
5780 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5781 aopPut (AOP (result), "a", offr + MSB16);
5785 /*-----------------------------------------------------------------*/
5786 /* shiftR2Left2Result - shift right two bytes from left to result */
5787 /*-----------------------------------------------------------------*/
5789 shiftR2Left2Result (operand * left, int offl,
5790 operand * result, int offr,
5791 int shCount, int sign)
5793 if (sameRegs (AOP (result), AOP (left)) &&
5794 ((offl + MSB16) == offr))
5796 /* don't crash result[offr] */
5797 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5798 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5802 movLeft2Result (left, offl, result, offr, 0);
5803 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5805 /* a:x >> shCount (x = lsb(result)) */
5807 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5809 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5810 if (getDataSize (result) > 1)
5811 aopPut (AOP (result), "a", offr + MSB16);
5814 /*-----------------------------------------------------------------*/
5815 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5816 /*-----------------------------------------------------------------*/
5818 shiftLLeftOrResult (operand * left, int offl,
5819 operand * result, int offr, int shCount)
5821 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5822 /* shift left accumulator */
5824 /* or with result */
5825 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5826 /* back to result */
5827 aopPut (AOP (result), "a", offr);
5830 /*-----------------------------------------------------------------*/
5831 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5832 /*-----------------------------------------------------------------*/
5834 shiftRLeftOrResult (operand * left, int offl,
5835 operand * result, int offr, int shCount)
5837 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5838 /* shift right accumulator */
5840 /* or with result */
5841 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5842 /* back to result */
5843 aopPut (AOP (result), "a", offr);
5846 /*-----------------------------------------------------------------*/
5847 /* genlshOne - left shift a one byte quantity by known count */
5848 /*-----------------------------------------------------------------*/
5850 genlshOne (operand * result, operand * left, int shCount)
5852 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5855 /*-----------------------------------------------------------------*/
5856 /* genlshTwo - left shift two bytes by known amount != 0 */
5857 /*-----------------------------------------------------------------*/
5859 genlshTwo (operand * result, operand * left, int shCount)
5863 size = getDataSize (result);
5865 /* if shCount >= 8 */
5873 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5875 movLeft2Result (left, LSB, result, MSB16, 0);
5877 aopPut (AOP (result), zero, LSB);
5880 /* 1 <= shCount <= 7 */
5884 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5886 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5890 /*-----------------------------------------------------------------*/
5891 /* shiftLLong - shift left one long from left to result */
5892 /* offl = LSB or MSB16 */
5893 /*-----------------------------------------------------------------*/
5895 shiftLLong (operand * left, operand * result, int offr)
5898 int size = AOP_SIZE (result);
5900 if (size >= LSB + offr)
5902 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5904 emitcode ("add", "a,acc");
5905 if (sameRegs (AOP (left), AOP (result)) &&
5906 size >= MSB16 + offr && offr != LSB)
5907 emitcode ("xch", "a,%s",
5908 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5910 aopPut (AOP (result), "a", LSB + offr);
5913 if (size >= MSB16 + offr)
5915 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5917 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5920 emitcode ("rlc", "a");
5921 if (sameRegs (AOP (left), AOP (result)) &&
5922 size >= MSB24 + offr && offr != LSB)
5923 emitcode ("xch", "a,%s",
5924 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5926 aopPut (AOP (result), "a", MSB16 + offr);
5929 if (size >= MSB24 + offr)
5931 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5933 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5936 emitcode ("rlc", "a");
5937 if (sameRegs (AOP (left), AOP (result)) &&
5938 size >= MSB32 + offr && offr != LSB)
5939 emitcode ("xch", "a,%s",
5940 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5942 aopPut (AOP (result), "a", MSB24 + offr);
5945 if (size > MSB32 + offr)
5947 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5949 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5952 emitcode ("rlc", "a");
5953 aopPut (AOP (result), "a", MSB32 + offr);
5956 aopPut (AOP (result), zero, LSB);
5959 /*-----------------------------------------------------------------*/
5960 /* genlshFour - shift four byte by a known amount != 0 */
5961 /*-----------------------------------------------------------------*/
5963 genlshFour (operand * result, operand * left, int shCount)
5967 size = AOP_SIZE (result);
5969 /* if shifting more that 3 bytes */
5974 /* lowest order of left goes to the highest
5975 order of the destination */
5976 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5978 movLeft2Result (left, LSB, result, MSB32, 0);
5979 aopPut (AOP (result), zero, LSB);
5980 aopPut (AOP (result), zero, MSB16);
5981 aopPut (AOP (result), zero, MSB32);
5985 /* more than two bytes */
5986 else if (shCount >= 16)
5988 /* lower order two bytes goes to higher order two bytes */
5990 /* if some more remaining */
5992 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5995 movLeft2Result (left, MSB16, result, MSB32, 0);
5996 movLeft2Result (left, LSB, result, MSB24, 0);
5998 aopPut (AOP (result), zero, MSB16);
5999 aopPut (AOP (result), zero, LSB);
6003 /* if more than 1 byte */
6004 else if (shCount >= 8)
6006 /* lower order three bytes goes to higher order three bytes */
6011 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6013 movLeft2Result (left, LSB, result, MSB16, 0);
6019 movLeft2Result (left, MSB24, result, MSB32, 0);
6020 movLeft2Result (left, MSB16, result, MSB24, 0);
6021 movLeft2Result (left, LSB, result, MSB16, 0);
6022 aopPut (AOP (result), zero, LSB);
6024 else if (shCount == 1)
6025 shiftLLong (left, result, MSB16);
6028 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6029 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6030 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6031 aopPut (AOP (result), zero, LSB);
6036 /* 1 <= shCount <= 7 */
6037 else if (shCount <= 2)
6039 shiftLLong (left, result, LSB);
6041 shiftLLong (result, result, LSB);
6043 /* 3 <= shCount <= 7, optimize */
6046 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6047 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6048 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6052 /*-----------------------------------------------------------------*/
6053 /* genLeftShiftLiteral - left shifting by known count */
6054 /*-----------------------------------------------------------------*/
6056 genLeftShiftLiteral (operand * left,
6061 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6064 freeAsmop (right, NULL, ic, TRUE);
6066 aopOp (left, ic, FALSE);
6067 aopOp (result, ic, FALSE);
6069 size = getSize (operandType (result));
6072 emitcode ("; shift left ", "result %d, left %d", size,
6076 /* I suppose that the left size >= result size */
6081 movLeft2Result (left, size, result, size, 0);
6085 else if (shCount >= (size * 8))
6087 aopPut (AOP (result), zero, size);
6093 genlshOne (result, left, shCount);
6098 genlshTwo (result, left, shCount);
6102 genlshFour (result, left, shCount);
6106 freeAsmop (left, NULL, ic, TRUE);
6107 freeAsmop (result, NULL, ic, TRUE);
6110 /*-----------------------------------------------------------------*/
6111 /* genLeftShift - generates code for left shifting */
6112 /*-----------------------------------------------------------------*/
6114 genLeftShift (iCode * ic)
6116 operand *left, *right, *result;
6119 symbol *tlbl, *tlbl1;
6121 right = IC_RIGHT (ic);
6122 left = IC_LEFT (ic);
6123 result = IC_RESULT (ic);
6125 aopOp (right, ic, FALSE);
6127 /* if the shift count is known then do it
6128 as efficiently as possible */
6129 if (AOP_TYPE (right) == AOP_LIT)
6131 genLeftShiftLiteral (left, right, result, ic);
6135 /* shift count is unknown then we have to form
6136 a loop get the loop count in B : Note: we take
6137 only the lower order byte since shifting
6138 more that 32 bits make no sense anyway, ( the
6139 largest size of an object can be only 32 bits ) */
6141 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6142 emitcode ("inc", "b");
6143 freeAsmop (right, NULL, ic, TRUE);
6144 aopOp (left, ic, FALSE);
6145 aopOp (result, ic, FALSE);
6147 /* now move the left to the result if they are not the
6149 if (!sameRegs (AOP (left), AOP (result)) &&
6150 AOP_SIZE (result) > 1)
6153 size = AOP_SIZE (result);
6157 l = aopGet (AOP (left), offset, FALSE, TRUE);
6158 if (*l == '@' && (IS_AOP_PREG (result)))
6161 emitcode ("mov", "a,%s", l);
6162 aopPut (AOP (result), "a", offset);
6165 aopPut (AOP (result), l, offset);
6170 tlbl = newiTempLabel (NULL);
6171 size = AOP_SIZE (result);
6173 tlbl1 = newiTempLabel (NULL);
6175 /* if it is only one byte then */
6178 symbol *tlbl1 = newiTempLabel (NULL);
6180 l = aopGet (AOP (left), 0, FALSE, FALSE);
6182 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6183 emitcode ("", "%05d$:", tlbl->key + 100);
6184 emitcode ("add", "a,acc");
6185 emitcode ("", "%05d$:", tlbl1->key + 100);
6186 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6187 aopPut (AOP (result), "a", 0);
6191 reAdjustPreg (AOP (result));
6193 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6194 emitcode ("", "%05d$:", tlbl->key + 100);
6195 l = aopGet (AOP (result), offset, FALSE, FALSE);
6197 emitcode ("add", "a,acc");
6198 aopPut (AOP (result), "a", offset++);
6201 l = aopGet (AOP (result), offset, FALSE, FALSE);
6203 emitcode ("rlc", "a");
6204 aopPut (AOP (result), "a", offset++);
6206 reAdjustPreg (AOP (result));
6208 emitcode ("", "%05d$:", tlbl1->key + 100);
6209 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6211 freeAsmop (left, NULL, ic, TRUE);
6212 freeAsmop (result, NULL, ic, TRUE);
6215 /*-----------------------------------------------------------------*/
6216 /* genrshOne - right shift a one byte quantity by known count */
6217 /*-----------------------------------------------------------------*/
6219 genrshOne (operand * result, operand * left,
6220 int shCount, int sign)
6222 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6225 /*-----------------------------------------------------------------*/
6226 /* genrshTwo - right shift two bytes by known amount != 0 */
6227 /*-----------------------------------------------------------------*/
6229 genrshTwo (operand * result, operand * left,
6230 int shCount, int sign)
6232 /* if shCount >= 8 */
6237 shiftR1Left2Result (left, MSB16, result, LSB,
6240 movLeft2Result (left, MSB16, result, LSB, sign);
6241 addSign (result, MSB16, sign);
6244 /* 1 <= shCount <= 7 */
6246 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6249 /*-----------------------------------------------------------------*/
6250 /* shiftRLong - shift right one long from left to result */
6251 /* offl = LSB or MSB16 */
6252 /*-----------------------------------------------------------------*/
6254 shiftRLong (operand * left, int offl,
6255 operand * result, int sign)
6258 emitcode ("clr", "c");
6259 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6261 emitcode ("mov", "c,acc.7");
6262 emitcode ("rrc", "a");
6263 aopPut (AOP (result), "a", MSB32 - offl);
6265 /* add sign of "a" */
6266 addSign (result, MSB32, sign);
6268 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6269 emitcode ("rrc", "a");
6270 aopPut (AOP (result), "a", MSB24 - offl);
6272 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6273 emitcode ("rrc", "a");
6274 aopPut (AOP (result), "a", MSB16 - offl);
6278 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6279 emitcode ("rrc", "a");
6280 aopPut (AOP (result), "a", LSB);
6284 /*-----------------------------------------------------------------*/
6285 /* genrshFour - shift four byte by a known amount != 0 */
6286 /*-----------------------------------------------------------------*/
6288 genrshFour (operand * result, operand * left,
6289 int shCount, int sign)
6291 /* if shifting more that 3 bytes */
6296 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6298 movLeft2Result (left, MSB32, result, LSB, sign);
6299 addSign (result, MSB16, sign);
6301 else if (shCount >= 16)
6305 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6308 movLeft2Result (left, MSB24, result, LSB, 0);
6309 movLeft2Result (left, MSB32, result, MSB16, sign);
6311 addSign (result, MSB24, sign);
6313 else if (shCount >= 8)
6317 shiftRLong (left, MSB16, result, sign);
6318 else if (shCount == 0)
6320 movLeft2Result (left, MSB16, result, LSB, 0);
6321 movLeft2Result (left, MSB24, result, MSB16, 0);
6322 movLeft2Result (left, MSB32, result, MSB24, sign);
6323 addSign (result, MSB32, sign);
6327 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6328 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6329 /* the last shift is signed */
6330 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6331 addSign (result, MSB32, sign);
6335 { /* 1 <= shCount <= 7 */
6338 shiftRLong (left, LSB, result, sign);
6340 shiftRLong (result, LSB, result, sign);
6344 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6345 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6346 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6351 /*-----------------------------------------------------------------*/
6352 /* genRightShiftLiteral - right shifting by known count */
6353 /*-----------------------------------------------------------------*/
6355 genRightShiftLiteral (operand * left,
6361 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6364 freeAsmop (right, NULL, ic, TRUE);
6366 aopOp (left, ic, FALSE);
6367 aopOp (result, ic, FALSE);
6370 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6374 size = getDataSize (left);
6375 /* test the LEFT size !!! */
6377 /* I suppose that the left size >= result size */
6380 size = getDataSize (result);
6382 movLeft2Result (left, size, result, size, 0);
6385 else if (shCount >= (size * 8))
6388 /* get sign in acc.7 */
6389 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6390 addSign (result, LSB, sign);
6397 genrshOne (result, left, shCount, sign);
6401 genrshTwo (result, left, shCount, sign);
6405 genrshFour (result, left, shCount, sign);
6411 freeAsmop (left, NULL, ic, TRUE);
6412 freeAsmop (result, NULL, ic, TRUE);
6416 /*-----------------------------------------------------------------*/
6417 /* genSignedRightShift - right shift of signed number */
6418 /*-----------------------------------------------------------------*/
6420 genSignedRightShift (iCode * ic)
6422 operand *right, *left, *result;
6425 symbol *tlbl, *tlbl1;
6427 /* we do it the hard way put the shift count in b
6428 and loop thru preserving the sign */
6430 right = IC_RIGHT (ic);
6431 left = IC_LEFT (ic);
6432 result = IC_RESULT (ic);
6434 aopOp (right, ic, FALSE);
6437 if (AOP_TYPE (right) == AOP_LIT)
6439 genRightShiftLiteral (left, right, result, ic, 1);
6442 /* shift count is unknown then we have to form
6443 a loop get the loop count in B : Note: we take
6444 only the lower order byte since shifting
6445 more that 32 bits make no sense anyway, ( the
6446 largest size of an object can be only 32 bits ) */
6448 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6449 emitcode ("inc", "b");
6450 freeAsmop (right, NULL, ic, TRUE);
6451 aopOp (left, ic, FALSE);
6452 aopOp (result, ic, FALSE);
6454 /* now move the left to the result if they are not the
6456 if (!sameRegs (AOP (left), AOP (result)) &&
6457 AOP_SIZE (result) > 1)
6460 size = AOP_SIZE (result);
6464 l = aopGet (AOP (left), offset, FALSE, TRUE);
6465 if (*l == '@' && IS_AOP_PREG (result))
6468 emitcode ("mov", "a,%s", l);
6469 aopPut (AOP (result), "a", offset);
6472 aopPut (AOP (result), l, offset);
6477 /* mov the highest order bit to OVR */
6478 tlbl = newiTempLabel (NULL);
6479 tlbl1 = newiTempLabel (NULL);
6481 size = AOP_SIZE (result);
6483 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6484 emitcode ("rlc", "a");
6485 emitcode ("mov", "ov,c");
6486 /* if it is only one byte then */
6489 l = aopGet (AOP (left), 0, FALSE, FALSE);
6491 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6492 emitcode ("", "%05d$:", tlbl->key + 100);
6493 emitcode ("mov", "c,ov");
6494 emitcode ("rrc", "a");
6495 emitcode ("", "%05d$:", tlbl1->key + 100);
6496 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6497 aopPut (AOP (result), "a", 0);
6501 reAdjustPreg (AOP (result));
6502 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6503 emitcode ("", "%05d$:", tlbl->key + 100);
6504 emitcode ("mov", "c,ov");
6507 l = aopGet (AOP (result), offset, FALSE, FALSE);
6509 emitcode ("rrc", "a");
6510 aopPut (AOP (result), "a", offset--);
6512 reAdjustPreg (AOP (result));
6513 emitcode ("", "%05d$:", tlbl1->key + 100);
6514 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6517 freeAsmop (left, NULL, ic, TRUE);
6518 freeAsmop (result, NULL, ic, TRUE);
6521 /*-----------------------------------------------------------------*/
6522 /* genRightShift - generate code for right shifting */
6523 /*-----------------------------------------------------------------*/
6525 genRightShift (iCode * ic)
6527 operand *right, *left, *result;
6531 symbol *tlbl, *tlbl1;
6533 /* if signed then we do it the hard way preserve the
6534 sign bit moving it inwards */
6535 retype = getSpec (operandType (IC_RESULT (ic)));
6537 if (!SPEC_USIGN (retype))
6539 genSignedRightShift (ic);
6543 /* signed & unsigned types are treated the same : i.e. the
6544 signed is NOT propagated inwards : quoting from the
6545 ANSI - standard : "for E1 >> E2, is equivalent to division
6546 by 2**E2 if unsigned or if it has a non-negative value,
6547 otherwise the result is implementation defined ", MY definition
6548 is that the sign does not get propagated */
6550 right = IC_RIGHT (ic);
6551 left = IC_LEFT (ic);
6552 result = IC_RESULT (ic);
6554 aopOp (right, ic, FALSE);
6556 /* if the shift count is known then do it
6557 as efficiently as possible */
6558 if (AOP_TYPE (right) == AOP_LIT)
6560 genRightShiftLiteral (left, right, result, ic, 0);
6564 /* shift count is unknown then we have to form
6565 a loop get the loop count in B : Note: we take
6566 only the lower order byte since shifting
6567 more that 32 bits make no sense anyway, ( the
6568 largest size of an object can be only 32 bits ) */
6570 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6571 emitcode ("inc", "b");
6572 freeAsmop (right, NULL, ic, TRUE);
6573 aopOp (left, ic, FALSE);
6574 aopOp (result, ic, FALSE);
6576 /* now move the left to the result if they are not the
6578 if (!sameRegs (AOP (left), AOP (result)) &&
6579 AOP_SIZE (result) > 1)
6582 size = AOP_SIZE (result);
6586 l = aopGet (AOP (left), offset, FALSE, TRUE);
6587 if (*l == '@' && IS_AOP_PREG (result))
6590 emitcode ("mov", "a,%s", l);
6591 aopPut (AOP (result), "a", offset);
6594 aopPut (AOP (result), l, offset);
6599 tlbl = newiTempLabel (NULL);
6600 tlbl1 = newiTempLabel (NULL);
6601 size = AOP_SIZE (result);
6604 /* if it is only one byte then */
6607 l = aopGet (AOP (left), 0, FALSE, FALSE);
6609 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6610 emitcode ("", "%05d$:", tlbl->key + 100);
6612 emitcode ("rrc", "a");
6613 emitcode ("", "%05d$:", tlbl1->key + 100);
6614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6615 aopPut (AOP (result), "a", 0);
6619 reAdjustPreg (AOP (result));
6620 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6621 emitcode ("", "%05d$:", tlbl->key + 100);
6625 l = aopGet (AOP (result), offset, FALSE, FALSE);
6627 emitcode ("rrc", "a");
6628 aopPut (AOP (result), "a", offset--);
6630 reAdjustPreg (AOP (result));
6632 emitcode ("", "%05d$:", tlbl1->key + 100);
6633 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6636 freeAsmop (left, NULL, ic, TRUE);
6637 freeAsmop (result, NULL, ic, TRUE);
6640 /*-----------------------------------------------------------------*/
6641 /* genUnpackBits - generates code for unpacking bits */
6642 /*-----------------------------------------------------------------*/
6644 genUnpackBits (operand * result, char *rname, int ptype)
6652 etype = getSpec (operandType (result));
6653 rsize = getSize (operandType (result));
6654 /* read the first byte */
6660 emitcode ("mov", "a,@%s", rname);
6664 emitcode ("movx", "a,@%s", rname);
6668 emitcode ("movx", "a,@dptr");
6672 emitcode ("clr", "a");
6673 emitcode ("movc", "a,%s", "@a+dptr");
6677 emitcode ("lcall", "__gptrget");
6681 rlen = SPEC_BLEN (etype);
6683 /* if we have bitdisplacement then it fits */
6684 /* into this byte completely or if length is */
6685 /* less than a byte */
6686 if ((shCnt = SPEC_BSTR (etype)) ||
6687 (SPEC_BLEN (etype) <= 8))
6690 /* shift right acc */
6693 emitcode ("anl", "a,#0x%02x",
6694 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6695 aopPut (AOP (result), "a", offset++);
6699 /* bit field did not fit in a byte */
6700 aopPut (AOP (result), "a", offset++);
6709 emitcode ("inc", "%s", rname);
6710 emitcode ("mov", "a,@%s", rname);
6714 emitcode ("inc", "%s", rname);
6715 emitcode ("movx", "a,@%s", rname);
6719 emitcode ("inc", "dptr");
6720 emitcode ("movx", "a,@dptr");
6724 emitcode ("clr", "a");
6725 emitcode ("inc", "dptr");
6726 emitcode ("movc", "a", "@a+dptr");
6730 emitcode ("inc", "dptr");
6731 emitcode ("lcall", "__gptrget");
6736 /* if we are done */
6740 aopPut (AOP (result), "a", offset++);
6746 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6748 aopPut (AOP (result), "a", offset++);
6756 aopPut (AOP (result), zero, offset++);
6762 /*-----------------------------------------------------------------*/
6763 /* genDataPointerGet - generates code when ptr offset is known */
6764 /*-----------------------------------------------------------------*/
6766 genDataPointerGet (operand * left,
6772 int size, offset = 0;
6773 aopOp (result, ic, TRUE);
6775 /* get the string representation of the name */
6776 l = aopGet (AOP (left), 0, FALSE, TRUE);
6777 size = AOP_SIZE (result);
6781 sprintf (buffer, "(%s + %d)", l + 1, offset);
6783 sprintf (buffer, "%s", l + 1);
6784 aopPut (AOP (result), buffer, offset++);
6787 freeAsmop (left, NULL, ic, TRUE);
6788 freeAsmop (result, NULL, ic, TRUE);
6791 /*-----------------------------------------------------------------*/
6792 /* genNearPointerGet - emitcode for near pointer fetch */
6793 /*-----------------------------------------------------------------*/
6795 genNearPointerGet (operand * left,
6802 sym_link *rtype, *retype;
6803 sym_link *ltype = operandType (left);
6806 rtype = operandType (result);
6807 retype = getSpec (rtype);
6809 aopOp (left, ic, FALSE);
6811 /* if left is rematerialisable and
6812 result is not bit variable type and
6813 the left is pointer to data space i.e
6814 lower 128 bytes of space */
6815 if (AOP_TYPE (left) == AOP_IMMD &&
6816 !IS_BITVAR (retype) &&
6817 DCL_TYPE (ltype) == POINTER)
6819 genDataPointerGet (left, result, ic);
6823 /* if the value is already in a pointer register
6824 then don't need anything more */
6825 if (!AOP_INPREG (AOP (left)))
6827 /* otherwise get a free pointer register */
6829 preg = getFreePtr (ic, &aop, FALSE);
6830 emitcode ("mov", "%s,%s",
6832 aopGet (AOP (left), 0, FALSE, TRUE));
6836 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6838 freeAsmop (left, NULL, ic, TRUE);
6839 aopOp (result, ic, FALSE);
6841 /* if bitfield then unpack the bits */
6842 if (IS_BITVAR (retype))
6843 genUnpackBits (result, rname, POINTER);
6846 /* we have can just get the values */
6847 int size = AOP_SIZE (result);
6852 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6855 emitcode ("mov", "a,@%s", rname);
6856 aopPut (AOP (result), "a", offset);
6860 sprintf (buffer, "@%s", rname);
6861 aopPut (AOP (result), buffer, offset);
6865 emitcode ("inc", "%s", rname);
6869 /* now some housekeeping stuff */
6872 /* we had to allocate for this iCode */
6873 freeAsmop (NULL, aop, ic, TRUE);
6877 /* we did not allocate which means left
6878 already in a pointer register, then
6879 if size > 0 && this could be used again
6880 we have to point it back to where it
6882 if (AOP_SIZE (result) > 1 &&
6883 !OP_SYMBOL (left)->remat &&
6884 (OP_SYMBOL (left)->liveTo > ic->seq ||
6887 int size = AOP_SIZE (result) - 1;
6889 emitcode ("dec", "%s", rname);
6894 freeAsmop (result, NULL, ic, TRUE);
6898 /*-----------------------------------------------------------------*/
6899 /* genPagedPointerGet - emitcode for paged pointer fetch */
6900 /*-----------------------------------------------------------------*/
6902 genPagedPointerGet (operand * left,
6909 sym_link *rtype, *retype;
6911 rtype = operandType (result);
6912 retype = getSpec (rtype);
6914 aopOp (left, ic, FALSE);
6916 /* if the value is already in a pointer register
6917 then don't need anything more */
6918 if (!AOP_INPREG (AOP (left)))
6920 /* otherwise get a free pointer register */
6922 preg = getFreePtr (ic, &aop, FALSE);
6923 emitcode ("mov", "%s,%s",
6925 aopGet (AOP (left), 0, FALSE, TRUE));
6929 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6931 freeAsmop (left, NULL, ic, TRUE);
6932 aopOp (result, ic, FALSE);
6934 /* if bitfield then unpack the bits */
6935 if (IS_BITVAR (retype))
6936 genUnpackBits (result, rname, PPOINTER);
6939 /* we have can just get the values */
6940 int size = AOP_SIZE (result);
6946 emitcode ("movx", "a,@%s", rname);
6947 aopPut (AOP (result), "a", offset);
6952 emitcode ("inc", "%s", rname);
6956 /* now some housekeeping stuff */
6959 /* we had to allocate for this iCode */
6960 freeAsmop (NULL, aop, ic, TRUE);
6964 /* we did not allocate which means left
6965 already in a pointer register, then
6966 if size > 0 && this could be used again
6967 we have to point it back to where it
6969 if (AOP_SIZE (result) > 1 &&
6970 !OP_SYMBOL (left)->remat &&
6971 (OP_SYMBOL (left)->liveTo > ic->seq ||
6974 int size = AOP_SIZE (result) - 1;
6976 emitcode ("dec", "%s", rname);
6981 freeAsmop (result, NULL, ic, TRUE);
6986 /*-----------------------------------------------------------------*/
6987 /* genFarPointerGet - gget value from far space */
6988 /*-----------------------------------------------------------------*/
6990 genFarPointerGet (operand * left,
6991 operand * result, iCode * ic)
6994 sym_link *retype = getSpec (operandType (result));
6996 aopOp (left, ic, FALSE);
6998 /* if the operand is already in dptr
6999 then we do nothing else we move the value to dptr */
7000 if (AOP_TYPE (left) != AOP_STR)
7002 /* if this is remateriazable */
7003 if (AOP_TYPE (left) == AOP_IMMD)
7004 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7006 { /* we need to get it byte by byte */
7007 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7008 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7011 /* so dptr know contains the address */
7012 freeAsmop (left, NULL, ic, TRUE);
7013 aopOp (result, ic, FALSE);
7015 /* if bit then unpack */
7016 if (IS_BITVAR (retype))
7017 genUnpackBits (result, "dptr", FPOINTER);
7020 size = AOP_SIZE (result);
7025 emitcode ("movx", "a,@dptr");
7026 aopPut (AOP (result), "a", offset++);
7028 emitcode ("inc", "dptr");
7032 freeAsmop (result, NULL, ic, TRUE);
7035 /*-----------------------------------------------------------------*/
7036 /* emitcodePointerGet - gget value from code space */
7037 /*-----------------------------------------------------------------*/
7039 emitcodePointerGet (operand * left,
7040 operand * result, iCode * ic)
7043 sym_link *retype = getSpec (operandType (result));
7045 aopOp (left, ic, FALSE);
7047 /* if the operand is already in dptr
7048 then we do nothing else we move the value to dptr */
7049 if (AOP_TYPE (left) != AOP_STR)
7051 /* if this is remateriazable */
7052 if (AOP_TYPE (left) == AOP_IMMD)
7053 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7055 { /* we need to get it byte by byte */
7056 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7057 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7060 /* so dptr know contains the address */
7061 freeAsmop (left, NULL, ic, TRUE);
7062 aopOp (result, ic, FALSE);
7064 /* if bit then unpack */
7065 if (IS_BITVAR (retype))
7066 genUnpackBits (result, "dptr", CPOINTER);
7069 size = AOP_SIZE (result);
7074 emitcode ("clr", "a");
7075 emitcode ("movc", "a,@a+dptr");
7076 aopPut (AOP (result), "a", offset++);
7078 emitcode ("inc", "dptr");
7082 freeAsmop (result, NULL, ic, TRUE);
7085 /*-----------------------------------------------------------------*/
7086 /* genGenPointerGet - gget value from generic pointer space */
7087 /*-----------------------------------------------------------------*/
7089 genGenPointerGet (operand * left,
7090 operand * result, iCode * ic)
7093 sym_link *retype = getSpec (operandType (result));
7095 aopOp (left, ic, FALSE);
7097 /* if the operand is already in dptr
7098 then we do nothing else we move the value to dptr */
7099 if (AOP_TYPE (left) != AOP_STR)
7101 /* if this is remateriazable */
7102 if (AOP_TYPE (left) == AOP_IMMD)
7104 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7105 emitcode ("mov", "b,#%d", pointerCode (retype));
7108 { /* we need to get it byte by byte */
7109 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7110 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7111 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7114 /* so dptr know contains the address */
7115 freeAsmop (left, NULL, ic, TRUE);
7116 aopOp (result, ic, FALSE);
7118 /* if bit then unpack */
7119 if (IS_BITVAR (retype))
7120 genUnpackBits (result, "dptr", GPOINTER);
7123 size = AOP_SIZE (result);
7128 emitcode ("lcall", "__gptrget");
7129 aopPut (AOP (result), "a", offset++);
7131 emitcode ("inc", "dptr");
7135 freeAsmop (result, NULL, ic, TRUE);
7138 /*-----------------------------------------------------------------*/
7139 /* genPointerGet - generate code for pointer get */
7140 /*-----------------------------------------------------------------*/
7142 genPointerGet (iCode * ic)
7144 operand *left, *result;
7145 sym_link *type, *etype;
7148 left = IC_LEFT (ic);
7149 result = IC_RESULT (ic);
7151 /* depending on the type of pointer we need to
7152 move it to the correct pointer register */
7153 type = operandType (left);
7154 etype = getSpec (type);
7155 /* if left is of type of pointer then it is simple */
7156 if (IS_PTR (type) && !IS_FUNC (type->next))
7157 p_type = DCL_TYPE (type);
7160 /* we have to go by the storage class */
7161 p_type = PTR_TYPE (SPEC_OCLS (etype));
7163 /* if (SPEC_OCLS(etype)->codesp ) { */
7164 /* p_type = CPOINTER ; */
7167 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7168 /* p_type = FPOINTER ; */
7170 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7171 /* p_type = PPOINTER; */
7173 /* if (SPEC_OCLS(etype) == idata ) */
7174 /* p_type = IPOINTER; */
7176 /* p_type = POINTER ; */
7179 /* now that we have the pointer type we assign
7180 the pointer values */
7186 genNearPointerGet (left, result, ic);
7190 genPagedPointerGet (left, result, ic);
7194 genFarPointerGet (left, result, ic);
7198 emitcodePointerGet (left, result, ic);
7202 genGenPointerGet (left, result, ic);
7208 /*-----------------------------------------------------------------*/
7209 /* genPackBits - generates code for packed bit storage */
7210 /*-----------------------------------------------------------------*/
7212 genPackBits (sym_link * etype,
7214 char *rname, int p_type)
7222 blen = SPEC_BLEN (etype);
7223 bstr = SPEC_BSTR (etype);
7225 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7228 /* if the bit lenth is less than or */
7229 /* it exactly fits a byte then */
7230 if (SPEC_BLEN (etype) <= 8)
7232 shCount = SPEC_BSTR (etype);
7234 /* shift left acc */
7237 if (SPEC_BLEN (etype) < 8)
7238 { /* if smaller than a byte */
7244 emitcode ("mov", "b,a");
7245 emitcode ("mov", "a,@%s", rname);
7249 emitcode ("mov", "b,a");
7250 emitcode ("movx", "a,@dptr");
7254 emitcode ("push", "b");
7255 emitcode ("push", "acc");
7256 emitcode ("lcall", "__gptrget");
7257 emitcode ("pop", "b");
7261 emitcode ("anl", "a,#0x%02x", (unsigned char)
7262 ((unsigned char) (0xFF << (blen + bstr)) |
7263 (unsigned char) (0xFF >> (8 - bstr))));
7264 emitcode ("orl", "a,b");
7265 if (p_type == GPOINTER)
7266 emitcode ("pop", "b");
7273 emitcode ("mov", "@%s,a", rname);
7277 emitcode ("movx", "@dptr,a");
7281 emitcode ("lcall", "__gptrput");
7286 if (SPEC_BLEN (etype) <= 8)
7289 emitcode ("inc", "%s", rname);
7290 rLen = SPEC_BLEN (etype);
7292 /* now generate for lengths greater than one byte */
7296 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7308 emitcode ("mov", "@%s,a", rname);
7311 emitcode ("mov", "@%s,%s", rname, l);
7316 emitcode ("movx", "@dptr,a");
7321 emitcode ("lcall", "__gptrput");
7324 emitcode ("inc", "%s", rname);
7329 /* last last was not complete */
7332 /* save the byte & read byte */
7336 emitcode ("mov", "b,a");
7337 emitcode ("mov", "a,@%s", rname);
7341 emitcode ("mov", "b,a");
7342 emitcode ("movx", "a,@dptr");
7346 emitcode ("push", "b");
7347 emitcode ("push", "acc");
7348 emitcode ("lcall", "__gptrget");
7349 emitcode ("pop", "b");
7353 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7354 emitcode ("orl", "a,b");
7357 if (p_type == GPOINTER)
7358 emitcode ("pop", "b");
7364 emitcode ("mov", "@%s,a", rname);
7368 emitcode ("movx", "@dptr,a");
7372 emitcode ("lcall", "__gptrput");
7376 /*-----------------------------------------------------------------*/
7377 /* genDataPointerSet - remat pointer to data space */
7378 /*-----------------------------------------------------------------*/
7380 genDataPointerSet (operand * right,
7384 int size, offset = 0;
7385 char *l, buffer[256];
7387 aopOp (right, ic, FALSE);
7389 l = aopGet (AOP (result), 0, FALSE, TRUE);
7390 size = AOP_SIZE (right);
7394 sprintf (buffer, "(%s + %d)", l + 1, offset);
7396 sprintf (buffer, "%s", l + 1);
7397 emitcode ("mov", "%s,%s", buffer,
7398 aopGet (AOP (right), offset++, FALSE, FALSE));
7401 freeAsmop (right, NULL, ic, TRUE);
7402 freeAsmop (result, NULL, ic, TRUE);
7405 /*-----------------------------------------------------------------*/
7406 /* genNearPointerSet - emitcode for near pointer put */
7407 /*-----------------------------------------------------------------*/
7409 genNearPointerSet (operand * right,
7416 sym_link *retype, *letype;
7417 sym_link *ptype = operandType (result);
7419 retype = getSpec (operandType (right));
7420 letype = getSpec (ptype);
7421 aopOp (result, ic, FALSE);
7423 /* if the result is rematerializable &
7424 in data space & not a bit variable */
7425 if (AOP_TYPE (result) == AOP_IMMD &&
7426 DCL_TYPE (ptype) == POINTER &&
7427 !IS_BITVAR (retype) &&
7428 !IS_BITVAR (letype))
7430 genDataPointerSet (right, result, ic);
7434 /* if the value is already in a pointer register
7435 then don't need anything more */
7436 if (!AOP_INPREG (AOP (result)))
7438 /* otherwise get a free pointer register */
7440 preg = getFreePtr (ic, &aop, FALSE);
7441 emitcode ("mov", "%s,%s",
7443 aopGet (AOP (result), 0, FALSE, TRUE));
7447 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7449 freeAsmop (result, NULL, ic, TRUE);
7450 aopOp (right, ic, FALSE);
7452 /* if bitfield then unpack the bits */
7453 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7454 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7457 /* we have can just get the values */
7458 int size = AOP_SIZE (right);
7463 l = aopGet (AOP (right), offset, FALSE, TRUE);
7467 emitcode ("mov", "@%s,a", rname);
7470 emitcode ("mov", "@%s,%s", rname, l);
7472 emitcode ("inc", "%s", rname);
7477 /* now some housekeeping stuff */
7480 /* we had to allocate for this iCode */
7481 freeAsmop (NULL, aop, ic, TRUE);
7485 /* we did not allocate which means left
7486 already in a pointer register, then
7487 if size > 0 && this could be used again
7488 we have to point it back to where it
7490 if (AOP_SIZE (right) > 1 &&
7491 !OP_SYMBOL (result)->remat &&
7492 (OP_SYMBOL (result)->liveTo > ic->seq ||
7495 int size = AOP_SIZE (right) - 1;
7497 emitcode ("dec", "%s", rname);
7502 freeAsmop (right, NULL, ic, TRUE);
7507 /*-----------------------------------------------------------------*/
7508 /* genPagedPointerSet - emitcode for Paged pointer put */
7509 /*-----------------------------------------------------------------*/
7511 genPagedPointerSet (operand * right,
7518 sym_link *retype, *letype;
7520 retype = getSpec (operandType (right));
7521 letype = getSpec (operandType (result));
7523 aopOp (result, ic, FALSE);
7525 /* if the value is already in a pointer register
7526 then don't need anything more */
7527 if (!AOP_INPREG (AOP (result)))
7529 /* otherwise get a free pointer register */
7531 preg = getFreePtr (ic, &aop, FALSE);
7532 emitcode ("mov", "%s,%s",
7534 aopGet (AOP (result), 0, FALSE, TRUE));
7538 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7540 freeAsmop (result, NULL, ic, TRUE);
7541 aopOp (right, ic, FALSE);
7543 /* if bitfield then unpack the bits */
7544 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7545 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7548 /* we have can just get the values */
7549 int size = AOP_SIZE (right);
7554 l = aopGet (AOP (right), offset, FALSE, TRUE);
7557 emitcode ("movx", "@%s,a", rname);
7560 emitcode ("inc", "%s", rname);
7566 /* now some housekeeping stuff */
7569 /* we had to allocate for this iCode */
7570 freeAsmop (NULL, aop, ic, TRUE);
7574 /* we did not allocate which means left
7575 already in a pointer register, then
7576 if size > 0 && this could be used again
7577 we have to point it back to where it
7579 if (AOP_SIZE (right) > 1 &&
7580 !OP_SYMBOL (result)->remat &&
7581 (OP_SYMBOL (result)->liveTo > ic->seq ||
7584 int size = AOP_SIZE (right) - 1;
7586 emitcode ("dec", "%s", rname);
7591 freeAsmop (right, NULL, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genFarPointerSet - set value from far space */
7598 /*-----------------------------------------------------------------*/
7600 genFarPointerSet (operand * right,
7601 operand * result, iCode * ic)
7604 sym_link *retype = getSpec (operandType (right));
7605 sym_link *letype = getSpec (operandType (result));
7606 aopOp (result, ic, FALSE);
7608 /* if the operand is already in dptr
7609 then we do nothing else we move the value to dptr */
7610 if (AOP_TYPE (result) != AOP_STR)
7612 /* if this is remateriazable */
7613 if (AOP_TYPE (result) == AOP_IMMD)
7614 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7616 { /* we need to get it byte by byte */
7617 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7618 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7621 /* so dptr know contains the address */
7622 freeAsmop (result, NULL, ic, TRUE);
7623 aopOp (right, ic, FALSE);
7625 /* if bit then unpack */
7626 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7627 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7630 size = AOP_SIZE (right);
7635 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7637 emitcode ("movx", "@dptr,a");
7639 emitcode ("inc", "dptr");
7643 freeAsmop (right, NULL, ic, TRUE);
7646 /*-----------------------------------------------------------------*/
7647 /* genGenPointerSet - set value from generic pointer space */
7648 /*-----------------------------------------------------------------*/
7650 genGenPointerSet (operand * right,
7651 operand * result, iCode * ic)
7654 sym_link *retype = getSpec (operandType (right));
7655 sym_link *letype = getSpec (operandType (result));
7657 aopOp (result, ic, FALSE);
7659 /* if the operand is already in dptr
7660 then we do nothing else we move the value to dptr */
7661 if (AOP_TYPE (result) != AOP_STR)
7663 /* if this is remateriazable */
7664 if (AOP_TYPE (result) == AOP_IMMD)
7666 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7667 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7670 { /* we need to get it byte by byte */
7671 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7672 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7673 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7676 /* so dptr know contains the address */
7677 freeAsmop (result, NULL, ic, TRUE);
7678 aopOp (right, ic, FALSE);
7680 /* if bit then unpack */
7681 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7682 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7685 size = AOP_SIZE (right);
7690 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7692 emitcode ("lcall", "__gptrput");
7694 emitcode ("inc", "dptr");
7698 freeAsmop (right, NULL, ic, TRUE);
7701 /*-----------------------------------------------------------------*/
7702 /* genPointerSet - stores the value into a pointer location */
7703 /*-----------------------------------------------------------------*/
7705 genPointerSet (iCode * ic)
7707 operand *right, *result;
7708 sym_link *type, *etype;
7711 right = IC_RIGHT (ic);
7712 result = IC_RESULT (ic);
7714 /* depending on the type of pointer we need to
7715 move it to the correct pointer register */
7716 type = operandType (result);
7717 etype = getSpec (type);
7718 /* if left is of type of pointer then it is simple */
7719 if (IS_PTR (type) && !IS_FUNC (type->next))
7721 p_type = DCL_TYPE (type);
7725 /* we have to go by the storage class */
7726 p_type = PTR_TYPE (SPEC_OCLS (etype));
7729 /* now that we have the pointer type we assign
7730 the pointer values */
7736 genNearPointerSet (right, result, ic);
7740 genPagedPointerSet (right, result, ic);
7744 genFarPointerSet (right, result, ic);
7748 genGenPointerSet (right, result, ic);
7754 /*-----------------------------------------------------------------*/
7755 /* genIfx - generate code for Ifx statement */
7756 /*-----------------------------------------------------------------*/
7758 genIfx (iCode * ic, iCode * popIc)
7760 operand *cond = IC_COND (ic);
7763 aopOp (cond, ic, FALSE);
7765 /* get the value into acc */
7766 if (AOP_TYPE (cond) != AOP_CRY)
7770 /* the result is now in the accumulator */
7771 freeAsmop (cond, NULL, ic, TRUE);
7773 /* if there was something to be popped then do it */
7777 /* if the condition is a bit variable */
7778 if (isbit && IS_ITEMP (cond) &&
7780 genIfxJump (ic, SPIL_LOC (cond)->rname);
7781 else if (isbit && !IS_ITEMP (cond))
7782 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7784 genIfxJump (ic, "a");
7789 /*-----------------------------------------------------------------*/
7790 /* genAddrOf - generates code for address of */
7791 /*-----------------------------------------------------------------*/
7793 genAddrOf (iCode * ic)
7795 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7798 aopOp (IC_RESULT (ic), ic, FALSE);
7800 /* if the operand is on the stack then we
7801 need to get the stack offset of this
7805 /* if it has an offset then we need to compute
7809 emitcode ("mov", "a,_bp");
7810 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7811 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7815 /* we can just move _bp */
7816 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7818 /* fill the result with zero */
7819 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7824 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7830 /* object not on stack then we need the name */
7831 size = AOP_SIZE (IC_RESULT (ic));
7836 char s[SDCC_NAME_MAX];
7838 sprintf (s, "#(%s >> %d)",
7842 sprintf (s, "#%s", sym->rname);
7843 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7847 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7851 /*-----------------------------------------------------------------*/
7852 /* genFarFarAssign - assignment when both are in far space */
7853 /*-----------------------------------------------------------------*/
7855 genFarFarAssign (operand * result, operand * right, iCode * ic)
7857 int size = AOP_SIZE (right);
7860 /* first push the right side on to the stack */
7863 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7865 emitcode ("push", "acc");
7868 freeAsmop (right, NULL, ic, FALSE);
7869 /* now assign DPTR to result */
7870 aopOp (result, ic, FALSE);
7871 size = AOP_SIZE (result);
7874 emitcode ("pop", "acc");
7875 aopPut (AOP (result), "a", --offset);
7877 freeAsmop (result, NULL, ic, FALSE);
7881 /*-----------------------------------------------------------------*/
7882 /* genAssign - generate code for assignment */
7883 /*-----------------------------------------------------------------*/
7885 genAssign (iCode * ic)
7887 operand *result, *right;
7889 unsigned long lit = 0L;
7891 result = IC_RESULT (ic);
7892 right = IC_RIGHT (ic);
7894 /* if they are the same */
7895 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7898 aopOp (right, ic, FALSE);
7900 /* special case both in far space */
7901 if ((AOP_TYPE (right) == AOP_DPTR ||
7902 AOP_TYPE (right) == AOP_DPTR2) &&
7903 IS_TRUE_SYMOP (result) &&
7904 isOperandInFarSpace (result))
7907 genFarFarAssign (result, right, ic);
7911 aopOp (result, ic, TRUE);
7913 /* if they are the same registers */
7914 if (sameRegs (AOP (right), AOP (result)))
7917 /* if the result is a bit */
7918 if (AOP_TYPE (result) == AOP_CRY)
7921 /* if the right size is a literal then
7922 we know what the value is */
7923 if (AOP_TYPE (right) == AOP_LIT)
7925 if (((int) operandLitValue (right)))
7926 aopPut (AOP (result), one, 0);
7928 aopPut (AOP (result), zero, 0);
7932 /* the right is also a bit variable */
7933 if (AOP_TYPE (right) == AOP_CRY)
7935 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7936 aopPut (AOP (result), "c", 0);
7942 aopPut (AOP (result), "a", 0);
7946 /* bit variables done */
7948 size = AOP_SIZE (result);
7950 if (AOP_TYPE (right) == AOP_LIT)
7951 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7953 (AOP_TYPE (result) != AOP_REG) &&
7954 (AOP_TYPE (right) == AOP_LIT) &&
7955 !IS_FLOAT (operandType (right)) &&
7958 emitcode ("clr", "a");
7961 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7962 aopPut (AOP (result), "a", size);
7964 aopPut (AOP (result),
7965 aopGet (AOP (right), size, FALSE, FALSE),
7973 aopPut (AOP (result),
7974 aopGet (AOP (right), offset, FALSE, FALSE),
7981 freeAsmop (right, NULL, ic, TRUE);
7982 freeAsmop (result, NULL, ic, TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genJumpTab - genrates code for jump table */
7987 /*-----------------------------------------------------------------*/
7989 genJumpTab (iCode * ic)
7994 aopOp (IC_JTCOND (ic), ic, FALSE);
7995 /* get the condition into accumulator */
7996 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7998 /* multiply by three */
7999 emitcode ("add", "a,acc");
8000 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8001 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8003 jtab = newiTempLabel (NULL);
8004 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8005 emitcode ("jmp", "@a+dptr");
8006 emitcode ("", "%05d$:", jtab->key + 100);
8007 /* now generate the jump labels */
8008 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8009 jtab = setNextItem (IC_JTLABELS (ic)))
8010 emitcode ("ljmp", "%05d$", jtab->key + 100);
8014 /*-----------------------------------------------------------------*/
8015 /* genCast - gen code for casting */
8016 /*-----------------------------------------------------------------*/
8018 genCast (iCode * ic)
8020 operand *result = IC_RESULT (ic);
8021 sym_link *ctype = operandType (IC_LEFT (ic));
8022 sym_link *rtype = operandType (IC_RIGHT (ic));
8023 operand *right = IC_RIGHT (ic);
8026 /* if they are equivalent then do nothing */
8027 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8030 aopOp (right, ic, FALSE);
8031 aopOp (result, ic, FALSE);
8033 /* if the result is a bit */
8034 if (AOP_TYPE (result) == AOP_CRY)
8036 /* if the right size is a literal then
8037 we know what the value is */
8038 if (AOP_TYPE (right) == AOP_LIT)
8040 if (((int) operandLitValue (right)))
8041 aopPut (AOP (result), one, 0);
8043 aopPut (AOP (result), zero, 0);
8048 /* the right is also a bit variable */
8049 if (AOP_TYPE (right) == AOP_CRY)
8051 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8052 aopPut (AOP (result), "c", 0);
8058 aopPut (AOP (result), "a", 0);
8062 /* if they are the same size : or less */
8063 if (AOP_SIZE (result) <= AOP_SIZE (right))
8066 /* if they are in the same place */
8067 if (sameRegs (AOP (right), AOP (result)))
8070 /* if they in different places then copy */
8071 size = AOP_SIZE (result);
8075 aopPut (AOP (result),
8076 aopGet (AOP (right), offset, FALSE, FALSE),
8084 /* if the result is of type pointer */
8089 sym_link *type = operandType (right);
8090 sym_link *etype = getSpec (type);
8092 /* pointer to generic pointer */
8093 if (IS_GENPTR (ctype))
8098 p_type = DCL_TYPE (type);
8101 /* we have to go by the storage class */
8102 p_type = PTR_TYPE (SPEC_OCLS (etype));
8105 /* the first two bytes are known */
8106 size = GPTRSIZE - 1;
8110 aopPut (AOP (result),
8111 aopGet (AOP (right), offset, FALSE, FALSE),
8115 /* the last byte depending on type */
8133 /* this should never happen */
8134 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8135 "got unknown pointer type");
8138 aopPut (AOP (result), l, GPTRSIZE - 1);
8142 /* just copy the pointers */
8143 size = AOP_SIZE (result);
8147 aopPut (AOP (result),
8148 aopGet (AOP (right), offset, FALSE, FALSE),
8155 /* so we now know that the size of destination is greater
8156 than the size of the source */
8157 /* we move to result for the size of source */
8158 size = AOP_SIZE (right);
8162 aopPut (AOP (result),
8163 aopGet (AOP (right), offset, FALSE, FALSE),
8168 /* now depending on the sign of the source && destination */
8169 size = AOP_SIZE (result) - AOP_SIZE (right);
8170 /* if unsigned or not an integral type */
8171 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8174 aopPut (AOP (result), zero, offset++);
8178 /* we need to extend the sign :{ */
8179 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8182 emitcode ("rlc", "a");
8183 emitcode ("subb", "a,acc");
8185 aopPut (AOP (result), "a", offset++);
8188 /* we are done hurray !!!! */
8191 freeAsmop (right, NULL, ic, TRUE);
8192 freeAsmop (result, NULL, ic, TRUE);
8196 /*-----------------------------------------------------------------*/
8197 /* genDjnz - generate decrement & jump if not zero instrucion */
8198 /*-----------------------------------------------------------------*/
8200 genDjnz (iCode * ic, iCode * ifx)
8206 /* if the if condition has a false label
8207 then we cannot save */
8211 /* if the minus is not of the form
8213 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8214 !IS_OP_LITERAL (IC_RIGHT (ic)))
8217 if (operandLitValue (IC_RIGHT (ic)) != 1)
8220 /* if the size of this greater than one then no
8222 if (getSize (operandType (IC_RESULT (ic))) > 1)
8225 /* otherwise we can save BIG */
8226 lbl = newiTempLabel (NULL);
8227 lbl1 = newiTempLabel (NULL);
8229 aopOp (IC_RESULT (ic), ic, FALSE);
8231 if (IS_AOP_PREG (IC_RESULT (ic)))
8233 emitcode ("dec", "%s",
8234 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8235 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8236 emitcode ("jnz", "%05d$", lbl->key + 100);
8240 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8243 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8244 emitcode ("", "%05d$:", lbl->key + 100);
8245 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8246 emitcode ("", "%05d$:", lbl1->key + 100);
8248 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8253 /*-----------------------------------------------------------------*/
8254 /* genReceive - generate code for a receive iCode */
8255 /*-----------------------------------------------------------------*/
8257 genReceive (iCode * ic)
8259 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8260 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8261 IS_TRUE_SYMOP (IC_RESULT (ic))))
8264 int size = getSize (operandType (IC_RESULT (ic)));
8265 int offset = fReturnSizeMCS51 - size;
8268 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8269 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8272 aopOp (IC_RESULT (ic), ic, FALSE);
8273 size = AOP_SIZE (IC_RESULT (ic));
8277 emitcode ("pop", "acc");
8278 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8285 aopOp (IC_RESULT (ic), ic, FALSE);
8287 assignResultValue (IC_RESULT (ic));
8290 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8293 /*-----------------------------------------------------------------*/
8294 /* gen51Code - generate code for 8051 based controllers */
8295 /*-----------------------------------------------------------------*/
8297 gen51Code (iCode * lic)
8302 lineHead = lineCurr = NULL;
8304 /* print the allocation information */
8306 printAllocInfo (currFunc, codeOutFile);
8307 /* if debug information required */
8308 /* if (options.debug && currFunc) { */
8311 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8313 if (IS_STATIC (currFunc->etype))
8314 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8316 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8319 /* stack pointer name */
8320 if (options.useXstack)
8326 for (ic = lic; ic; ic = ic->next)
8329 if (cln != ic->lineno)
8334 emitcode ("", "C$%s$%d$%d$%d ==.",
8335 FileBaseName (ic->filename), ic->lineno,
8336 ic->level, ic->block);
8339 emitcode (";", "%s %d", ic->filename, ic->lineno);
8342 /* if the result is marked as
8343 spilt and rematerializable or code for
8344 this has already been generated then
8346 if (resultRemat (ic) || ic->generated)
8349 /* depending on the operation */
8369 /* IPOP happens only when trying to restore a
8370 spilt live range, if there is an ifx statement
8371 following this pop then the if statement might
8372 be using some of the registers being popped which
8373 would destory the contents of the register so
8374 we need to check for this condition and handle it */
8376 ic->next->op == IFX &&
8377 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8378 genIfx (ic->next, ic);
8396 genEndFunction (ic);
8416 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8433 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8437 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8444 /* note these two are xlated by algebraic equivalence
8445 during parsing SDCC.y */
8446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8447 "got '>=' or '<=' shouldn't have come here");
8451 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8463 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8467 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8471 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8498 case GET_VALUE_AT_ADDRESS:
8503 if (POINTER_SET (ic))
8530 addSet (&_G.sendSet, ic);
8535 /* piCode(ic,stdout); */
8541 /* now we are ready to call the
8542 peep hole optimizer */
8543 if (!options.nopeep)
8544 peepHole (&lineHead);
8546 /* now do the actual printing */
8547 printLine (lineHead, codeOutFile);