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"))
1046 symbol *lbl = newiTempLabel (NULL);
1047 emitcode ("clr", "c");
1048 emitcode ("jz", "%05d$", lbl->key + 100);
1049 emitcode ("cpl", "c");
1050 emitcode ("", "%05d$:", lbl->key + 100);
1051 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1059 if (strcmp (aop->aopu.aop_str[offset], s))
1060 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1065 if (!offset && (strcmp (s, "acc") == 0))
1068 if (strcmp (aop->aopu.aop_str[offset], s))
1069 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1073 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1074 "aopPut got unsupported aop->type");
1082 /*-----------------------------------------------------------------*/
1083 /* pointToEnd :- points to the last byte of the operand */
1084 /*-----------------------------------------------------------------*/
1086 pointToEnd (asmop * aop)
1092 aop->coff = count = (aop->size - 1);
1098 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1102 emitcode ("inc", "dptr");
1109 /*-----------------------------------------------------------------*/
1110 /* reAdjustPreg - points a register back to where it should */
1111 /*-----------------------------------------------------------------*/
1113 reAdjustPreg (asmop * aop)
1116 if ((aop->coff==0) || aop->size <= 1)
1124 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 if (aop->type == AOP_DPTR2)
1134 emitcode ("lcall", "__decdptr");
1137 if (aop->type == AOP_DPTR2)
1147 #define AOP(op) op->aop
1148 #define AOP_TYPE(op) AOP(op)->type
1149 #define AOP_SIZE(op) AOP(op)->size
1150 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1151 AOP_TYPE(x) == AOP_R0))
1153 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1154 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1157 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1158 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1159 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1161 /*-----------------------------------------------------------------*/
1162 /* genNotFloat - generates not for float operations */
1163 /*-----------------------------------------------------------------*/
1165 genNotFloat (operand * op, operand * res)
1171 /* we will put 127 in the first byte of
1173 aopPut (AOP (res), "#127", 0);
1174 size = AOP_SIZE (op) - 1;
1177 l = aopGet (op->aop, offset++, FALSE, FALSE);
1182 emitcode ("orl", "a,%s",
1184 offset++, FALSE, FALSE));
1187 tlbl = newiTempLabel (NULL);
1188 aopPut (res->aop, one, 1);
1189 emitcode ("jz", "%05d$", (tlbl->key + 100));
1190 aopPut (res->aop, zero, 1);
1191 emitcode ("", "%05d$:", (tlbl->key + 100));
1193 size = res->aop->size - 2;
1195 /* put zeros in the rest */
1197 aopPut (res->aop, zero, offset++);
1200 /*-----------------------------------------------------------------*/
1201 /* opIsGptr: returns non-zero if the passed operand is */
1202 /* a generic pointer type. */
1203 /*-----------------------------------------------------------------*/
1205 opIsGptr (operand * op)
1207 sym_link *type = operandType (op);
1209 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1216 /*-----------------------------------------------------------------*/
1217 /* getDataSize - get the operand data size */
1218 /*-----------------------------------------------------------------*/
1220 getDataSize (operand * op)
1223 size = AOP_SIZE (op);
1224 if (size == GPTRSIZE)
1226 sym_link *type = operandType (op);
1227 if (IS_GENPTR (type))
1229 /* generic pointer; arithmetic operations
1230 * should ignore the high byte (pointer type).
1238 /*-----------------------------------------------------------------*/
1239 /* outAcc - output Acc */
1240 /*-----------------------------------------------------------------*/
1242 outAcc (operand * result)
1245 size = getDataSize (result);
1248 aopPut (AOP (result), "a", 0);
1251 /* unsigned or positive */
1254 aopPut (AOP (result), zero, offset++);
1259 /*-----------------------------------------------------------------*/
1260 /* outBitC - output a bit C */
1261 /*-----------------------------------------------------------------*/
1263 outBitC (operand * result)
1265 /* if the result is bit */
1266 if (AOP_TYPE (result) == AOP_CRY)
1267 aopPut (AOP (result), "c", 0);
1270 emitcode ("clr", "a");
1271 emitcode ("rlc", "a");
1276 /*-----------------------------------------------------------------*/
1277 /* toBoolean - emit code for orl a,operator(sizeop) */
1278 /*-----------------------------------------------------------------*/
1280 toBoolean (operand * oper)
1282 int size = AOP_SIZE (oper) - 1;
1284 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1286 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1290 /*-----------------------------------------------------------------*/
1291 /* genNot - generate code for ! operation */
1292 /*-----------------------------------------------------------------*/
1297 sym_link *optype = operandType (IC_LEFT (ic));
1299 /* assign asmOps to operand & result */
1300 aopOp (IC_LEFT (ic), ic, FALSE);
1301 aopOp (IC_RESULT (ic), ic, TRUE);
1303 /* if in bit space then a special case */
1304 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1306 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1307 emitcode ("cpl", "c");
1308 outBitC (IC_RESULT (ic));
1312 /* if type float then do float */
1313 if (IS_FLOAT (optype))
1315 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1319 toBoolean (IC_LEFT (ic));
1321 tlbl = newiTempLabel (NULL);
1322 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1323 emitcode ("", "%05d$:", tlbl->key + 100);
1324 outBitC (IC_RESULT (ic));
1327 /* release the aops */
1328 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1329 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1333 /*-----------------------------------------------------------------*/
1334 /* genCpl - generate code for complement */
1335 /*-----------------------------------------------------------------*/
1343 /* assign asmOps to operand & result */
1344 aopOp (IC_LEFT (ic), ic, FALSE);
1345 aopOp (IC_RESULT (ic), ic, TRUE);
1347 /* if both are in bit space then
1349 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1350 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1353 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1354 emitcode ("cpl", "c");
1355 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1359 size = AOP_SIZE (IC_RESULT (ic));
1362 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1364 emitcode ("cpl", "a");
1365 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1370 /* release the aops */
1371 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1375 /*-----------------------------------------------------------------*/
1376 /* genUminusFloat - unary minus for floating points */
1377 /*-----------------------------------------------------------------*/
1379 genUminusFloat (operand * op, operand * result)
1381 int size, offset = 0;
1383 /* for this we just need to flip the
1384 first it then copy the rest in place */
1385 size = AOP_SIZE (op) - 1;
1386 l = aopGet (AOP (op), 3, FALSE, FALSE);
1390 emitcode ("cpl", "acc.7");
1391 aopPut (AOP (result), "a", 3);
1395 aopPut (AOP (result),
1396 aopGet (AOP (op), offset, FALSE, FALSE),
1402 /*-----------------------------------------------------------------*/
1403 /* genUminus - unary minus code generation */
1404 /*-----------------------------------------------------------------*/
1406 genUminus (iCode * ic)
1409 sym_link *optype, *rtype;
1413 aopOp (IC_LEFT (ic), ic, FALSE);
1414 aopOp (IC_RESULT (ic), ic, TRUE);
1416 /* if both in bit space then special
1418 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1419 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1422 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1423 emitcode ("cpl", "c");
1424 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1428 optype = operandType (IC_LEFT (ic));
1429 rtype = operandType (IC_RESULT (ic));
1431 /* if float then do float stuff */
1432 if (IS_FLOAT (optype))
1434 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1438 /* otherwise subtract from zero */
1439 size = AOP_SIZE (IC_LEFT (ic));
1444 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1445 if (!strcmp (l, "a"))
1449 emitcode ("cpl", "a");
1450 emitcode ("addc", "a,#0");
1456 emitcode ("clr", "a");
1457 emitcode ("subb", "a,%s", l);
1459 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1462 /* if any remaining bytes in the result */
1463 /* we just need to propagate the sign */
1464 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1466 emitcode ("rlc", "a");
1467 emitcode ("subb", "a,acc");
1469 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1473 /* release the aops */
1474 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1478 /*-----------------------------------------------------------------*/
1479 /* saveRegisters - will look for a call and save the registers */
1480 /*-----------------------------------------------------------------*/
1482 saveRegisters (iCode * lic)
1490 for (ic = lic; ic; ic = ic->next)
1491 if (ic->op == CALL || ic->op == PCALL)
1496 fprintf (stderr, "found parameter push with no function call\n");
1500 /* if the registers have been saved already then
1502 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1505 /* find the registers in use at this time
1506 and push them away to safety */
1507 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1511 if (options.useXstack)
1513 if (bitVectBitValue (rsave, R0_IDX))
1514 emitcode ("mov", "b,r0");
1515 emitcode ("mov", "r0,%s", spname);
1516 for (i = 0; i < mcs51_nRegs; i++)
1518 if (bitVectBitValue (rsave, i))
1521 emitcode ("mov", "a,b");
1523 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1524 emitcode ("movx", "@r0,a");
1525 emitcode ("inc", "r0");
1528 emitcode ("mov", "%s,r0", spname);
1529 if (bitVectBitValue (rsave, R0_IDX))
1530 emitcode ("mov", "r0,b");
1533 for (i = 0; i < mcs51_nRegs; i++)
1535 if (bitVectBitValue (rsave, i))
1536 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1539 detype = getSpec (operandType (IC_LEFT (ic)));
1541 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1542 IS_ISR (currFunc->etype) &&
1545 saverbank (SPEC_BANK (detype), ic, TRUE);
1548 /*-----------------------------------------------------------------*/
1549 /* unsaveRegisters - pop the pushed registers */
1550 /*-----------------------------------------------------------------*/
1552 unsaveRegisters (iCode * ic)
1556 /* find the registers in use at this time
1557 and push them away to safety */
1558 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1561 if (options.useXstack)
1563 emitcode ("mov", "r0,%s", spname);
1564 for (i = mcs51_nRegs; i >= 0; i--)
1566 if (bitVectBitValue (rsave, i))
1568 emitcode ("dec", "r0");
1569 emitcode ("movx", "a,@r0");
1571 emitcode ("mov", "b,a");
1573 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1577 emitcode ("mov", "%s,r0", spname);
1578 if (bitVectBitValue (rsave, R0_IDX))
1579 emitcode ("mov", "r0,b");
1582 for (i = mcs51_nRegs; i >= 0; i--)
1584 if (bitVectBitValue (rsave, i))
1585 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1591 /*-----------------------------------------------------------------*/
1593 /*-----------------------------------------------------------------*/
1595 pushSide (operand * oper, int size)
1600 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1601 if (AOP_TYPE (oper) != AOP_REG &&
1602 AOP_TYPE (oper) != AOP_DIR &&
1605 emitcode ("mov", "a,%s", l);
1606 emitcode ("push", "acc");
1609 emitcode ("push", "%s", l);
1613 /*-----------------------------------------------------------------*/
1614 /* assignResultValue - */
1615 /*-----------------------------------------------------------------*/
1617 assignResultValue (operand * oper)
1620 int size = AOP_SIZE (oper);
1623 aopPut (AOP (oper), fReturn[offset], offset);
1629 /*-----------------------------------------------------------------*/
1630 /* genXpush - pushes onto the external stack */
1631 /*-----------------------------------------------------------------*/
1633 genXpush (iCode * ic)
1635 asmop *aop = newAsmop (0);
1637 int size, offset = 0;
1639 aopOp (IC_LEFT (ic), ic, FALSE);
1640 r = getFreePtr (ic, &aop, FALSE);
1643 emitcode ("mov", "%s,_spx", r->name);
1645 size = AOP_SIZE (IC_LEFT (ic));
1649 char *l = aopGet (AOP (IC_LEFT (ic)),
1650 offset++, FALSE, FALSE);
1652 emitcode ("movx", "@%s,a", r->name);
1653 emitcode ("inc", "%s", r->name);
1658 emitcode ("mov", "_spx,%s", r->name);
1660 freeAsmop (NULL, aop, ic, TRUE);
1661 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1664 /*-----------------------------------------------------------------*/
1665 /* genIpush - genrate code for pushing this gets a little complex */
1666 /*-----------------------------------------------------------------*/
1668 genIpush (iCode * ic)
1670 int size, offset = 0;
1674 /* if this is not a parm push : ie. it is spill push
1675 and spill push is always done on the local stack */
1679 /* and the item is spilt then do nothing */
1680 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1683 aopOp (IC_LEFT (ic), ic, FALSE);
1684 size = AOP_SIZE (IC_LEFT (ic));
1685 /* push it on the stack */
1688 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1694 emitcode ("push", "%s", l);
1699 /* this is a paramter push: in this case we call
1700 the routine to find the call and save those
1701 registers that need to be saved */
1704 /* if use external stack then call the external
1705 stack pushing routine */
1706 if (options.useXstack)
1712 /* then do the push */
1713 aopOp (IC_LEFT (ic), ic, FALSE);
1716 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1717 size = AOP_SIZE (IC_LEFT (ic));
1721 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1722 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1723 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1726 emitcode ("mov", "a,%s", l);
1727 emitcode ("push", "acc");
1730 emitcode ("push", "%s", l);
1733 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1736 /*-----------------------------------------------------------------*/
1737 /* genIpop - recover the registers: can happen only for spilling */
1738 /*-----------------------------------------------------------------*/
1740 genIpop (iCode * ic)
1745 /* if the temp was not pushed then */
1746 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1749 aopOp (IC_LEFT (ic), ic, FALSE);
1750 size = AOP_SIZE (IC_LEFT (ic));
1751 offset = (size - 1);
1753 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1756 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1759 /*-----------------------------------------------------------------*/
1760 /* unsaverbank - restores the resgister bank from stack */
1761 /*-----------------------------------------------------------------*/
1763 unsaverbank (int bank, iCode * ic, bool popPsw)
1771 if (options.useXstack)
1774 r = getFreePtr (ic, &aop, FALSE);
1777 emitcode ("mov", "%s,_spx", r->name);
1778 emitcode ("movx", "a,@%s", r->name);
1779 emitcode ("mov", "psw,a");
1780 emitcode ("dec", "%s", r->name);
1784 emitcode ("pop", "psw");
1787 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1789 if (options.useXstack)
1791 emitcode ("movx", "a,@%s", r->name);
1792 emitcode ("mov", "(%s+%d),a",
1793 regs8051[i].base, 8 * bank + regs8051[i].offset);
1794 emitcode ("dec", "%s", r->name);
1798 emitcode ("pop", "(%s+%d)",
1799 regs8051[i].base, 8 * bank + regs8051[i].offset);
1802 if (options.useXstack)
1805 emitcode ("mov", "_spx,%s", r->name);
1806 freeAsmop (NULL, aop, ic, TRUE);
1811 /*-----------------------------------------------------------------*/
1812 /* saverbank - saves an entire register bank on the stack */
1813 /*-----------------------------------------------------------------*/
1815 saverbank (int bank, iCode * ic, bool pushPsw)
1821 if (options.useXstack)
1825 r = getFreePtr (ic, &aop, FALSE);
1826 emitcode ("mov", "%s,_spx", r->name);
1830 for (i = 0; i < mcs51_nRegs; i++)
1832 if (options.useXstack)
1834 emitcode ("inc", "%s", r->name);
1835 emitcode ("mov", "a,(%s+%d)",
1836 regs8051[i].base, 8 * bank + regs8051[i].offset);
1837 emitcode ("movx", "@%s,a", r->name);
1840 emitcode ("push", "(%s+%d)",
1841 regs8051[i].base, 8 * bank + regs8051[i].offset);
1846 if (options.useXstack)
1848 emitcode ("mov", "a,psw");
1849 emitcode ("movx", "@%s,a", r->name);
1850 emitcode ("inc", "%s", r->name);
1851 emitcode ("mov", "_spx,%s", r->name);
1852 freeAsmop (NULL, aop, ic, TRUE);
1856 emitcode ("push", "psw");
1858 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1864 /*-----------------------------------------------------------------*/
1865 /* genCall - generates a call statement */
1866 /*-----------------------------------------------------------------*/
1868 genCall (iCode * ic)
1872 /* if caller saves & we have not saved then */
1876 /* if we are calling a function that is not using
1877 the same register bank then we need to save the
1878 destination registers on the stack */
1879 detype = getSpec (operandType (IC_LEFT (ic)));
1881 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1882 IS_ISR (currFunc->etype) &&
1885 saverbank (SPEC_BANK (detype), ic, TRUE);
1887 /* if send set is not empty the assign */
1892 for (sic = setFirstItem (_G.sendSet); sic;
1893 sic = setNextItem (_G.sendSet))
1895 int size, offset = 0;
1896 aopOp (IC_LEFT (sic), sic, FALSE);
1897 size = AOP_SIZE (IC_LEFT (sic));
1900 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1902 if (strcmp (l, fReturn[offset]))
1903 emitcode ("mov", "%s,%s",
1908 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1913 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1914 OP_SYMBOL (IC_LEFT (ic))->rname :
1915 OP_SYMBOL (IC_LEFT (ic))->name));
1917 /* if we need assign a result value */
1918 if ((IS_ITEMP (IC_RESULT (ic)) &&
1919 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1920 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1921 IS_TRUE_SYMOP (IC_RESULT (ic)))
1925 aopOp (IC_RESULT (ic), ic, FALSE);
1928 assignResultValue (IC_RESULT (ic));
1930 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1933 /* adjust the stack for parameters if
1938 if (ic->parmBytes > 3)
1940 emitcode ("mov", "a,%s", spname);
1941 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1942 emitcode ("mov", "%s,a", spname);
1945 for (i = 0; i < ic->parmBytes; i++)
1946 emitcode ("dec", "%s", spname);
1950 /* if register bank was saved then pop them */
1952 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1954 /* if we hade saved some registers then unsave them */
1955 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1956 unsaveRegisters (ic);
1961 /*-----------------------------------------------------------------*/
1962 /* genPcall - generates a call by pointer statement */
1963 /*-----------------------------------------------------------------*/
1965 genPcall (iCode * ic)
1968 symbol *rlbl = newiTempLabel (NULL);
1971 /* if caller saves & we have not saved then */
1975 /* if we are calling a function that is not using
1976 the same register bank then we need to save the
1977 destination registers on the stack */
1978 detype = getSpec (operandType (IC_LEFT (ic)));
1980 IS_ISR (currFunc->etype) &&
1981 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1982 saverbank (SPEC_BANK (detype), ic, TRUE);
1985 /* push the return address on to the stack */
1986 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1987 emitcode ("push", "acc");
1988 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1989 emitcode ("push", "acc");
1991 /* now push the calling address */
1992 aopOp (IC_LEFT (ic), ic, FALSE);
1994 pushSide (IC_LEFT (ic), FPTRSIZE);
1996 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1998 /* if send set is not empty the assign */
2003 for (sic = setFirstItem (_G.sendSet); sic;
2004 sic = setNextItem (_G.sendSet))
2006 int size, offset = 0;
2007 aopOp (IC_LEFT (sic), sic, FALSE);
2008 size = AOP_SIZE (IC_LEFT (sic));
2011 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2013 if (strcmp (l, fReturn[offset]))
2014 emitcode ("mov", "%s,%s",
2019 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2024 emitcode ("ret", "");
2025 emitcode ("", "%05d$:", (rlbl->key + 100));
2028 /* if we need assign a result value */
2029 if ((IS_ITEMP (IC_RESULT (ic)) &&
2030 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2031 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2032 IS_TRUE_SYMOP (IC_RESULT (ic)))
2036 aopOp (IC_RESULT (ic), ic, FALSE);
2039 assignResultValue (IC_RESULT (ic));
2041 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2044 /* adjust the stack for parameters if
2049 if (ic->parmBytes > 3)
2051 emitcode ("mov", "a,%s", spname);
2052 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2053 emitcode ("mov", "%s,a", spname);
2056 for (i = 0; i < ic->parmBytes; i++)
2057 emitcode ("dec", "%s", spname);
2061 /* if register bank was saved then unsave them */
2063 (SPEC_BANK (currFunc->etype) !=
2064 SPEC_BANK (detype)))
2065 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2067 /* if we hade saved some registers then
2070 unsaveRegisters (ic);
2074 /*-----------------------------------------------------------------*/
2075 /* resultRemat - result is rematerializable */
2076 /*-----------------------------------------------------------------*/
2078 resultRemat (iCode * ic)
2080 if (SKIP_IC (ic) || ic->op == IFX)
2083 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2085 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2086 if (sym->remat && !POINTER_SET (ic))
2093 #if defined(__BORLANDC__) || defined(_MSC_VER)
2094 #define STRCASECMP stricmp
2096 #define STRCASECMP strcasecmp
2099 /*-----------------------------------------------------------------*/
2100 /* inExcludeList - return 1 if the string is in exclude Reg list */
2101 /*-----------------------------------------------------------------*/
2103 inExcludeList (char *s)
2107 if (options.excludeRegs[i] &&
2108 STRCASECMP (options.excludeRegs[i], "none") == 0)
2111 for (i = 0; options.excludeRegs[i]; i++)
2113 if (options.excludeRegs[i] &&
2114 STRCASECMP (s, options.excludeRegs[i]) == 0)
2120 /*-----------------------------------------------------------------*/
2121 /* genFunction - generated code for function entry */
2122 /*-----------------------------------------------------------------*/
2124 genFunction (iCode * ic)
2130 /* create the function header */
2131 emitcode (";", "-----------------------------------------");
2132 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2133 emitcode (";", "-----------------------------------------");
2135 emitcode ("", "%s:", sym->rname);
2136 fetype = getSpec (operandType (IC_LEFT (ic)));
2138 /* if critical function then turn interrupts off */
2139 if (SPEC_CRTCL (fetype))
2140 emitcode ("clr", "ea");
2142 /* here we need to generate the equates for the
2143 register bank if required */
2144 if (SPEC_BANK (fetype) != rbank)
2148 rbank = SPEC_BANK (fetype);
2149 for (i = 0; i < mcs51_nRegs; i++)
2151 if (strcmp (regs8051[i].base, "0") == 0)
2152 emitcode ("", "%s = 0x%02x",
2154 8 * rbank + regs8051[i].offset);
2156 emitcode ("", "%s = %s + 0x%02x",
2159 8 * rbank + regs8051[i].offset);
2163 /* if this is an interrupt service routine then
2164 save acc, b, dpl, dph */
2165 if (IS_ISR (sym->etype))
2168 if (!inExcludeList ("acc"))
2169 emitcode ("push", "acc");
2170 if (!inExcludeList ("b"))
2171 emitcode ("push", "b");
2172 if (!inExcludeList ("dpl"))
2173 emitcode ("push", "dpl");
2174 if (!inExcludeList ("dph"))
2175 emitcode ("push", "dph");
2176 /* if this isr has no bank i.e. is going to
2177 run with bank 0 , then we need to save more
2179 if (!SPEC_BANK (sym->etype))
2182 /* if this function does not call any other
2183 function then we can be economical and
2184 save only those registers that are used */
2189 /* if any registers used */
2192 /* save the registers used */
2193 for (i = 0; i < sym->regsUsed->size; i++)
2195 if (bitVectBitValue (sym->regsUsed, i) ||
2196 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2197 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2204 /* this function has a function call cannot
2205 determines register usage so we will have the
2207 saverbank (0, ic, FALSE);
2213 /* if callee-save to be used for this function
2214 then save the registers being used in this function */
2215 if (sym->calleeSave)
2219 /* if any registers used */
2222 /* save the registers used */
2223 for (i = 0; i < sym->regsUsed->size; i++)
2225 if (bitVectBitValue (sym->regsUsed, i) ||
2226 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2228 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2236 /* set the register bank to the desired value */
2237 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2239 emitcode ("push", "psw");
2240 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2243 if (IS_RENT (sym->etype) || options.stackAuto)
2246 if (options.useXstack)
2248 emitcode ("mov", "r0,%s", spname);
2249 emitcode ("mov", "a,_bp");
2250 emitcode ("movx", "@r0,a");
2251 emitcode ("inc", "%s", spname);
2255 /* set up the stack */
2256 emitcode ("push", "_bp"); /* save the callers stack */
2258 emitcode ("mov", "_bp,%s", spname);
2261 /* adjust the stack for the function */
2267 werror (W_STACK_OVERFLOW, sym->name);
2269 if (i > 3 && sym->recvSize < 4)
2272 emitcode ("mov", "a,sp");
2273 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2274 emitcode ("mov", "sp,a");
2279 emitcode ("inc", "sp");
2285 emitcode ("mov", "a,_spx");
2286 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2287 emitcode ("mov", "_spx,a");
2292 /*-----------------------------------------------------------------*/
2293 /* genEndFunction - generates epilogue for functions */
2294 /*-----------------------------------------------------------------*/
2296 genEndFunction (iCode * ic)
2298 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2300 if (IS_RENT (sym->etype) || options.stackAuto)
2302 emitcode ("mov", "%s,_bp", spname);
2305 /* if use external stack but some variables were
2306 added to the local stack then decrement the
2308 if (options.useXstack && sym->stack)
2310 emitcode ("mov", "a,sp");
2311 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2312 emitcode ("mov", "sp,a");
2316 if ((IS_RENT (sym->etype) || options.stackAuto))
2318 if (options.useXstack)
2320 emitcode ("mov", "r0,%s", spname);
2321 emitcode ("movx", "a,@r0");
2322 emitcode ("mov", "_bp,a");
2323 emitcode ("dec", "%s", spname);
2327 emitcode ("pop", "_bp");
2331 /* restore the register bank */
2332 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2333 emitcode ("pop", "psw");
2335 if (IS_ISR (sym->etype))
2338 /* now we need to restore the registers */
2339 /* if this isr has no bank i.e. is going to
2340 run with bank 0 , then we need to save more
2342 if (!SPEC_BANK (sym->etype))
2345 /* if this function does not call any other
2346 function then we can be economical and
2347 save only those registers that are used */
2352 /* if any registers used */
2355 /* save the registers used */
2356 for (i = sym->regsUsed->size; i >= 0; i--)
2358 if (bitVectBitValue (sym->regsUsed, i) ||
2359 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2360 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2367 /* this function has a function call cannot
2368 determines register usage so we will have the
2370 unsaverbank (0, ic, FALSE);
2374 if (!inExcludeList ("dph"))
2375 emitcode ("pop", "dph");
2376 if (!inExcludeList ("dpl"))
2377 emitcode ("pop", "dpl");
2378 if (!inExcludeList ("b"))
2379 emitcode ("pop", "b");
2380 if (!inExcludeList ("acc"))
2381 emitcode ("pop", "acc");
2383 if (SPEC_CRTCL (sym->etype))
2384 emitcode ("setb", "ea");
2386 /* if debug then send end of function */
2387 /* if (options.debug && currFunc) { */
2391 emitcode ("", "C$%s$%d$%d$%d ==.",
2392 FileBaseName (ic->filename), currFunc->lastLine,
2393 ic->level, ic->block);
2394 if (IS_STATIC (currFunc->etype))
2395 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2397 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2401 emitcode ("reti", "");
2405 if (SPEC_CRTCL (sym->etype))
2406 emitcode ("setb", "ea");
2408 if (sym->calleeSave)
2412 /* if any registers used */
2415 /* save the registers used */
2416 for (i = sym->regsUsed->size; i >= 0; i--)
2418 if (bitVectBitValue (sym->regsUsed, i) ||
2419 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2420 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2426 /* if debug then send end of function */
2430 emitcode ("", "C$%s$%d$%d$%d ==.",
2431 FileBaseName (ic->filename), currFunc->lastLine,
2432 ic->level, ic->block);
2433 if (IS_STATIC (currFunc->etype))
2434 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2436 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2440 emitcode ("ret", "");
2445 /*-----------------------------------------------------------------*/
2446 /* genRet - generate code for return statement */
2447 /*-----------------------------------------------------------------*/
2451 int size, offset = 0, pushed = 0;
2453 /* if we have no return value then
2454 just generate the "ret" */
2458 /* we have something to return then
2459 move the return value into place */
2460 aopOp (IC_LEFT (ic), ic, FALSE);
2461 size = AOP_SIZE (IC_LEFT (ic));
2466 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2469 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2471 emitcode ("push", "%s", l);
2476 l = aopGet (AOP (IC_LEFT (ic)), offset,
2478 if (strcmp (fReturn[offset], l))
2479 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2488 if (strcmp (fReturn[pushed], "a"))
2489 emitcode ("pop", fReturn[pushed]);
2491 emitcode ("pop", "acc");
2494 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2497 /* generate a jump to the return label
2498 if the next is not the return statement */
2499 if (!(ic->next && ic->next->op == LABEL &&
2500 IC_LABEL (ic->next) == returnLabel))
2502 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2506 /*-----------------------------------------------------------------*/
2507 /* genLabel - generates a label */
2508 /*-----------------------------------------------------------------*/
2510 genLabel (iCode * ic)
2512 /* special case never generate */
2513 if (IC_LABEL (ic) == entryLabel)
2516 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2519 /*-----------------------------------------------------------------*/
2520 /* genGoto - generates a ljmp */
2521 /*-----------------------------------------------------------------*/
2523 genGoto (iCode * ic)
2525 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2528 /*-----------------------------------------------------------------*/
2529 /* findLabelBackwards: walks back through the iCode chain looking */
2530 /* for the given label. Returns number of iCode instructions */
2531 /* between that label and given ic. */
2532 /* Returns zero if label not found. */
2533 /*-----------------------------------------------------------------*/
2535 findLabelBackwards (iCode * ic, int key)
2544 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2546 /* printf("findLabelBackwards = %d\n", count); */
2554 /*-----------------------------------------------------------------*/
2555 /* genPlusIncr :- does addition with increment if possible */
2556 /*-----------------------------------------------------------------*/
2558 genPlusIncr (iCode * ic)
2560 unsigned int icount;
2561 unsigned int size = getDataSize (IC_RESULT (ic));
2563 /* will try to generate an increment */
2564 /* if the right side is not a literal
2566 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2569 /* if the literal value of the right hand side
2570 is greater than 4 then it is not worth it */
2571 if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2574 /* if increment 16 bits in register */
2575 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2583 /* If the next instruction is a goto and the goto target
2584 * is < 10 instructions previous to this, we can generate
2585 * jumps straight to that target.
2587 if (ic->next && ic->next->op == GOTO
2588 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2589 && labelRange <= 10)
2591 emitcode (";", "tail increment optimized");
2592 tlbl = IC_LABEL (ic->next);
2597 tlbl = newiTempLabel (NULL);
2600 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2601 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2602 IS_AOP_PREG (IC_RESULT (ic)))
2603 emitcode ("cjne", "%s,#0x00,%05d$"
2604 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2608 emitcode ("clr", "a");
2609 emitcode ("cjne", "a,%s,%05d$"
2610 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2614 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2617 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2618 IS_AOP_PREG (IC_RESULT (ic)))
2619 emitcode ("cjne", "%s,#0x00,%05d$"
2620 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2623 emitcode ("cjne", "a,%s,%05d$"
2624 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2627 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2631 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2632 IS_AOP_PREG (IC_RESULT (ic)))
2633 emitcode ("cjne", "%s,#0x00,%05d$"
2634 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2638 emitcode ("cjne", "a,%s,%05d$"
2639 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2642 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2647 emitcode ("", "%05d$:", tlbl->key + 100);
2652 /* if the sizes are greater than 1 then we cannot */
2653 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2654 AOP_SIZE (IC_LEFT (ic)) > 1)
2657 /* we can if the aops of the left & result match or
2658 if they are in registers and the registers are the
2660 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2665 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2666 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2667 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2673 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2682 /*-----------------------------------------------------------------*/
2683 /* outBitAcc - output a bit in acc */
2684 /*-----------------------------------------------------------------*/
2686 outBitAcc (operand * result)
2688 symbol *tlbl = newiTempLabel (NULL);
2689 /* if the result is a bit */
2690 if (AOP_TYPE (result) == AOP_CRY)
2692 aopPut (AOP (result), "a", 0);
2696 emitcode ("jz", "%05d$", tlbl->key + 100);
2697 emitcode ("mov", "a,%s", one);
2698 emitcode ("", "%05d$:", tlbl->key + 100);
2703 /*-----------------------------------------------------------------*/
2704 /* genPlusBits - generates code for addition of two bits */
2705 /*-----------------------------------------------------------------*/
2707 genPlusBits (iCode * ic)
2709 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2711 symbol *lbl = newiTempLabel (NULL);
2712 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2713 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2714 emitcode ("cpl", "c");
2715 emitcode ("", "%05d$:", (lbl->key + 100));
2716 outBitC (IC_RESULT (ic));
2720 emitcode ("clr", "a");
2721 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2722 emitcode ("rlc", "a");
2723 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2724 emitcode ("addc", "a,#0x00");
2725 outAcc (IC_RESULT (ic));
2730 /* This is the original version of this code.
2732 * This is being kept around for reference,
2733 * because I am not entirely sure I got it right...
2736 adjustArithmeticResult (iCode * ic)
2738 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2739 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2740 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2741 aopPut (AOP (IC_RESULT (ic)),
2742 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2745 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2746 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2747 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2748 aopPut (AOP (IC_RESULT (ic)),
2749 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2752 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2753 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2754 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2755 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2756 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2759 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2760 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2764 /* This is the pure and virtuous version of this code.
2765 * I'm pretty certain it's right, but not enough to toss the old
2769 adjustArithmeticResult (iCode * ic)
2771 if (opIsGptr (IC_RESULT (ic)) &&
2772 opIsGptr (IC_LEFT (ic)) &&
2773 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2775 aopPut (AOP (IC_RESULT (ic)),
2776 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2780 if (opIsGptr (IC_RESULT (ic)) &&
2781 opIsGptr (IC_RIGHT (ic)) &&
2782 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2784 aopPut (AOP (IC_RESULT (ic)),
2785 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2789 if (opIsGptr (IC_RESULT (ic)) &&
2790 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2791 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2792 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2793 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2796 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2797 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2802 /*-----------------------------------------------------------------*/
2803 /* genPlus - generates code for addition */
2804 /*-----------------------------------------------------------------*/
2806 genPlus (iCode * ic)
2808 int size, offset = 0;
2810 /* special cases :- */
2812 aopOp (IC_LEFT (ic), ic, FALSE);
2813 aopOp (IC_RIGHT (ic), ic, FALSE);
2814 aopOp (IC_RESULT (ic), ic, TRUE);
2816 /* if literal, literal on the right or
2817 if left requires ACC or right is already
2819 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2820 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2821 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2823 operand *t = IC_RIGHT (ic);
2824 IC_RIGHT (ic) = IC_LEFT (ic);
2828 /* if both left & right are in bit
2830 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2831 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2837 /* if left in bit space & right literal */
2838 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2839 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2841 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2842 /* if result in bit space */
2843 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2845 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2846 emitcode ("cpl", "c");
2847 outBitC (IC_RESULT (ic));
2851 size = getDataSize (IC_RESULT (ic));
2854 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2855 emitcode ("addc", "a,#00");
2856 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2862 /* if I can do an increment instead
2863 of add then GOOD for ME */
2864 if (genPlusIncr (ic) == TRUE)
2867 size = getDataSize (IC_RESULT (ic));
2871 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2873 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2875 emitcode ("add", "a,%s",
2876 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2878 emitcode ("addc", "a,%s",
2879 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2883 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2885 emitcode ("add", "a,%s",
2886 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2888 emitcode ("addc", "a,%s",
2889 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2891 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2894 adjustArithmeticResult (ic);
2897 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2898 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2899 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2902 /*-----------------------------------------------------------------*/
2903 /* genMinusDec :- does subtraction with deccrement if possible */
2904 /*-----------------------------------------------------------------*/
2906 genMinusDec (iCode * ic)
2908 unsigned int icount;
2909 unsigned int size = getDataSize (IC_RESULT (ic));
2911 /* will try to generate an increment */
2912 /* if the right side is not a literal
2914 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2917 /* if the literal value of the right hand side
2918 is greater than 4 then it is not worth it */
2919 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2922 /* if decrement 16 bits in register */
2923 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2931 /* If the next instruction is a goto and the goto target
2932 * is <= 10 instructions previous to this, we can generate
2933 * jumps straight to that target.
2935 if (ic->next && ic->next->op == GOTO
2936 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2937 && labelRange <= 10)
2939 emitcode (";", "tail decrement optimized");
2940 tlbl = IC_LABEL (ic->next);
2945 tlbl = newiTempLabel (NULL);
2949 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2950 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2951 IS_AOP_PREG (IC_RESULT (ic)))
2952 emitcode ("cjne", "%s,#0xff,%05d$"
2953 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2957 emitcode ("mov", "a,#0xff");
2958 emitcode ("cjne", "a,%s,%05d$"
2959 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2962 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2965 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2966 IS_AOP_PREG (IC_RESULT (ic)))
2967 emitcode ("cjne", "%s,#0xff,%05d$"
2968 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2972 emitcode ("cjne", "a,%s,%05d$"
2973 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2976 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2980 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2981 IS_AOP_PREG (IC_RESULT (ic)))
2982 emitcode ("cjne", "%s,#0xff,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2987 emitcode ("cjne", "a,%s,%05d$"
2988 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2991 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2995 emitcode ("", "%05d$:", tlbl->key + 100);
3000 /* if the sizes are greater than 1 then we cannot */
3001 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3002 AOP_SIZE (IC_LEFT (ic)) > 1)
3005 /* we can if the aops of the left & result match or
3006 if they are in registers and the registers are the
3008 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3012 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3020 /*-----------------------------------------------------------------*/
3021 /* addSign - complete with sign */
3022 /*-----------------------------------------------------------------*/
3024 addSign (operand * result, int offset, int sign)
3026 int size = (getDataSize (result) - offset);
3031 emitcode ("rlc", "a");
3032 emitcode ("subb", "a,acc");
3034 aopPut (AOP (result), "a", offset++);
3038 aopPut (AOP (result), zero, offset++);
3042 /*-----------------------------------------------------------------*/
3043 /* genMinusBits - generates code for subtraction of two bits */
3044 /*-----------------------------------------------------------------*/
3046 genMinusBits (iCode * ic)
3048 symbol *lbl = newiTempLabel (NULL);
3049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3051 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3052 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3053 emitcode ("cpl", "c");
3054 emitcode ("", "%05d$:", (lbl->key + 100));
3055 outBitC (IC_RESULT (ic));
3059 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3060 emitcode ("subb", "a,acc");
3061 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3062 emitcode ("inc", "a");
3063 emitcode ("", "%05d$:", (lbl->key + 100));
3064 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3065 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3069 /*-----------------------------------------------------------------*/
3070 /* genMinus - generates code for subtraction */
3071 /*-----------------------------------------------------------------*/
3073 genMinus (iCode * ic)
3075 int size, offset = 0;
3076 unsigned long lit = 0L;
3078 aopOp (IC_LEFT (ic), ic, FALSE);
3079 aopOp (IC_RIGHT (ic), ic, FALSE);
3080 aopOp (IC_RESULT (ic), ic, TRUE);
3082 /* special cases :- */
3083 /* if both left & right are in bit space */
3084 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3085 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3091 /* if I can do an decrement instead
3092 of subtract then GOOD for ME */
3093 if (genMinusDec (ic) == TRUE)
3096 size = getDataSize (IC_RESULT (ic));
3098 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3104 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3108 /* if literal, add a,#-lit, else normal subb */
3111 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3112 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3113 emitcode ("subb", "a,%s",
3114 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3117 /* first add without previous c */
3119 emitcode ("add", "a,#0x%02x",
3120 (unsigned int) (lit & 0x0FFL));
3122 emitcode ("addc", "a,#0x%02x",
3123 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3125 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3128 adjustArithmeticResult (ic);
3131 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3132 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3133 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3137 /*-----------------------------------------------------------------*/
3138 /* genMultbits :- multiplication of bits */
3139 /*-----------------------------------------------------------------*/
3141 genMultbits (operand * left,
3145 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3146 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3151 /*-----------------------------------------------------------------*/
3152 /* genMultOneByte : 8*8=8/16 bit multiplication */
3153 /*-----------------------------------------------------------------*/
3156 genMultOneByte (operand * left,
3160 sym_link *opetype = operandType (result);
3165 /* (if two literals, the value is computed before) */
3166 /* if one literal, literal on the right */
3167 if (AOP_TYPE (left) == AOP_LIT)
3174 size = AOP_SIZE (result);
3175 /* signed or unsigned */
3176 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3177 l = aopGet (AOP (left), 0, FALSE, FALSE);
3179 emitcode ("mul", "ab");
3180 /* if result size = 1, mul signed = mul unsigned */
3181 aopPut (AOP (result), "a", 0);
3184 if (SPEC_USIGN (opetype))
3186 aopPut (AOP (result), "b", 1);
3188 /* for filling the MSBs */
3189 emitcode ("clr", "a");
3193 emitcode ("mov", "a,b");
3195 /* adjust the MSB if left or right neg */
3197 /* if one literal */
3198 if (AOP_TYPE (right) == AOP_LIT)
3200 /* AND literal negative */
3201 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3203 /* adjust MSB (c==0 after mul) */
3204 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3209 lbl = newiTempLabel (NULL);
3210 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3211 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3212 emitcode ("", "%05d$:", (lbl->key + 100));
3213 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3214 lbl = newiTempLabel (NULL);
3215 emitcode ("jc", "%05d$", (lbl->key + 100));
3216 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3217 emitcode ("", "%05d$:", (lbl->key + 100));
3220 lbl = newiTempLabel (NULL);
3221 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3222 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3223 emitcode ("", "%05d$:", (lbl->key + 100));
3224 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3225 lbl = newiTempLabel (NULL);
3226 emitcode ("jc", "%05d$", (lbl->key + 100));
3227 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3228 emitcode ("", "%05d$:", (lbl->key + 100));
3230 aopPut (AOP (result), "a", 1);
3234 emitcode ("rlc", "a");
3235 emitcode ("subb", "a,acc");
3242 aopPut (AOP (result), "a", offset++);
3247 genMultOneByte (operand * left,
3251 sym_link *opetype = operandType (result);
3253 int size=AOP_SIZE(result);
3255 //emitcode (";",__FUNCTION__);
3256 if (size<1 || size>2) {
3257 // this should never happen
3258 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3259 AOP_SIZE(result), __FUNCTION__, lineno);
3263 /* (if two literals: the value is computed before) */
3264 /* if one literal, literal on the right */
3265 if (AOP_TYPE (left) == AOP_LIT)
3270 //emitcode (";", "swapped left and right");
3273 if (SPEC_USIGN(opetype)
3274 // ignore the sign of left and right, what else can we do?
3275 || (SPEC_USIGN(operandType(left)) &&
3276 SPEC_USIGN(operandType(right)))) {
3277 // just an unsigned 8*8=8/16 multiply
3278 //emitcode (";","unsigned");
3279 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3280 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3281 emitcode ("mul", "ab");
3282 aopPut (AOP (result), "a", 0);
3284 aopPut (AOP (result), "b", 1);
3289 // we have to do a signed multiply
3291 //emitcode (";", "signed");
3292 emitcode ("clr", "F0"); // reset sign flag
3293 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3294 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3296 lbl=newiTempLabel(NULL);
3297 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3298 // left side is negative, 8-bit two's complement, this fails for -128
3299 emitcode ("setb", "F0"); // set sign flag
3300 emitcode ("cpl", "a");
3301 emitcode ("inc", "a");
3303 emitcode ("", "%05d$:", lbl->key+100);
3304 emitcode ("xch", "a,b");
3307 if (AOP_TYPE(right)==AOP_LIT) {
3308 /* AND literal negative */
3309 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3310 // two's complement for literal<0
3311 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3312 emitcode ("cpl", "a");
3313 emitcode ("inc", "a");
3316 lbl=newiTempLabel(NULL);
3317 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3318 // right side is negative, 8-bit two's complement
3319 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3320 emitcode ("cpl", "a");
3321 emitcode ("inc", "a");
3322 emitcode ("", "%05d$:", lbl->key+100);
3324 emitcode ("mul", "ab");
3326 lbl=newiTempLabel(NULL);
3327 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3328 // only ONE op was negative, we have to do a 8/16-bit two's complement
3329 emitcode ("cpl", "a"); // lsb
3331 emitcode ("inc", "a");
3333 emitcode ("add", "a,#1");
3334 emitcode ("xch", "a,b");
3335 emitcode ("cpl", "a"); // msb
3336 emitcode ("addc", "a,#0");
3337 emitcode ("xch", "a,b");
3340 emitcode ("", "%05d$:", lbl->key+100);
3341 aopPut (AOP (result), "a", 0);
3343 aopPut (AOP (result), "b", 1);
3348 /*-----------------------------------------------------------------*/
3349 /* genMult - generates code for multiplication */
3350 /*-----------------------------------------------------------------*/
3352 genMult (iCode * ic)
3354 operand *left = IC_LEFT (ic);
3355 operand *right = IC_RIGHT (ic);
3356 operand *result = IC_RESULT (ic);
3358 /* assign the amsops */
3359 aopOp (left, ic, FALSE);
3360 aopOp (right, ic, FALSE);
3361 aopOp (result, ic, TRUE);
3363 /* special cases first */
3365 if (AOP_TYPE (left) == AOP_CRY &&
3366 AOP_TYPE (right) == AOP_CRY)
3368 genMultbits (left, right, result);
3372 /* if both are of size == 1 */
3373 if (AOP_SIZE (left) == 1 &&
3374 AOP_SIZE (right) == 1)
3376 genMultOneByte (left, right, result);
3380 /* should have been converted to function call */
3384 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3385 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (result, NULL, ic, TRUE);
3389 /*-----------------------------------------------------------------*/
3390 /* genDivbits :- division of bits */
3391 /*-----------------------------------------------------------------*/
3393 genDivbits (operand * left,
3400 /* the result must be bit */
3401 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3402 l = aopGet (AOP (left), 0, FALSE, FALSE);
3406 emitcode ("div", "ab");
3407 emitcode ("rrc", "a");
3408 aopPut (AOP (result), "c", 0);
3411 /*-----------------------------------------------------------------*/
3412 /* genDivOneByte : 8 bit division */
3413 /*-----------------------------------------------------------------*/
3415 genDivOneByte (operand * left,
3419 sym_link *opetype = operandType (result);
3424 size = AOP_SIZE (result) - 1;
3426 /* signed or unsigned */
3427 if (SPEC_USIGN (opetype))
3429 /* unsigned is easy */
3430 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3431 l = aopGet (AOP (left), 0, FALSE, FALSE);
3433 emitcode ("div", "ab");
3434 aopPut (AOP (result), "a", 0);
3436 aopPut (AOP (result), zero, offset++);
3440 /* signed is a little bit more difficult */
3442 /* save the signs of the operands */
3443 l = aopGet (AOP (left), 0, FALSE, FALSE);
3445 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3446 emitcode ("push", "acc"); /* save it on the stack */
3448 /* now sign adjust for both left & right */
3449 l = aopGet (AOP (right), 0, FALSE, FALSE);
3451 lbl = newiTempLabel (NULL);
3452 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3453 emitcode ("cpl", "a");
3454 emitcode ("inc", "a");
3455 emitcode ("", "%05d$:", (lbl->key + 100));
3456 emitcode ("mov", "b,a");
3458 /* sign adjust left side */
3459 l = aopGet (AOP (left), 0, FALSE, FALSE);
3462 lbl = newiTempLabel (NULL);
3463 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3464 emitcode ("cpl", "a");
3465 emitcode ("inc", "a");
3466 emitcode ("", "%05d$:", (lbl->key + 100));
3468 /* now the division */
3469 emitcode ("div", "ab");
3470 /* we are interested in the lower order
3472 emitcode ("mov", "b,a");
3473 lbl = newiTempLabel (NULL);
3474 emitcode ("pop", "acc");
3475 /* if there was an over flow we don't
3476 adjust the sign of the result */
3477 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3478 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3480 emitcode ("clr", "a");
3481 emitcode ("subb", "a,b");
3482 emitcode ("mov", "b,a");
3483 emitcode ("", "%05d$:", (lbl->key + 100));
3485 /* now we are done */
3486 aopPut (AOP (result), "b", 0);
3489 emitcode ("mov", "c,b.7");
3490 emitcode ("subb", "a,acc");
3493 aopPut (AOP (result), "a", offset++);
3497 /*-----------------------------------------------------------------*/
3498 /* genDiv - generates code for division */
3499 /*-----------------------------------------------------------------*/
3503 operand *left = IC_LEFT (ic);
3504 operand *right = IC_RIGHT (ic);
3505 operand *result = IC_RESULT (ic);
3507 /* assign the amsops */
3508 aopOp (left, ic, FALSE);
3509 aopOp (right, ic, FALSE);
3510 aopOp (result, ic, TRUE);
3512 /* special cases first */
3514 if (AOP_TYPE (left) == AOP_CRY &&
3515 AOP_TYPE (right) == AOP_CRY)
3517 genDivbits (left, right, result);
3521 /* if both are of size == 1 */
3522 if (AOP_SIZE (left) == 1 &&
3523 AOP_SIZE (right) == 1)
3525 genDivOneByte (left, right, result);
3529 /* should have been converted to function call */
3532 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3533 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3534 freeAsmop (result, NULL, ic, TRUE);
3537 /*-----------------------------------------------------------------*/
3538 /* genModbits :- modulus of bits */
3539 /*-----------------------------------------------------------------*/
3541 genModbits (operand * left,
3548 /* the result must be bit */
3549 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3550 l = aopGet (AOP (left), 0, FALSE, FALSE);
3554 emitcode ("div", "ab");
3555 emitcode ("mov", "a,b");
3556 emitcode ("rrc", "a");
3557 aopPut (AOP (result), "c", 0);
3560 /*-----------------------------------------------------------------*/
3561 /* genModOneByte : 8 bit modulus */
3562 /*-----------------------------------------------------------------*/
3564 genModOneByte (operand * left,
3568 sym_link *opetype = operandType (result);
3572 /* signed or unsigned */
3573 if (SPEC_USIGN (opetype))
3575 /* unsigned is easy */
3576 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3577 l = aopGet (AOP (left), 0, FALSE, FALSE);
3579 emitcode ("div", "ab");
3580 aopPut (AOP (result), "b", 0);
3584 /* signed is a little bit more difficult */
3586 /* save the signs of the operands */
3587 l = aopGet (AOP (left), 0, FALSE, FALSE);
3590 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3591 emitcode ("push", "acc"); /* save it on the stack */
3593 /* now sign adjust for both left & right */
3594 l = aopGet (AOP (right), 0, FALSE, FALSE);
3597 lbl = newiTempLabel (NULL);
3598 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3599 emitcode ("cpl", "a");
3600 emitcode ("inc", "a");
3601 emitcode ("", "%05d$:", (lbl->key + 100));
3602 emitcode ("mov", "b,a");
3604 /* sign adjust left side */
3605 l = aopGet (AOP (left), 0, FALSE, FALSE);
3608 lbl = newiTempLabel (NULL);
3609 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3610 emitcode ("cpl", "a");
3611 emitcode ("inc", "a");
3612 emitcode ("", "%05d$:", (lbl->key + 100));
3614 /* now the multiplication */
3615 emitcode ("div", "ab");
3616 /* we are interested in the lower order
3618 lbl = newiTempLabel (NULL);
3619 emitcode ("pop", "acc");
3620 /* if there was an over flow we don't
3621 adjust the sign of the result */
3622 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3623 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3625 emitcode ("clr", "a");
3626 emitcode ("subb", "a,b");
3627 emitcode ("mov", "b,a");
3628 emitcode ("", "%05d$:", (lbl->key + 100));
3630 /* now we are done */
3631 aopPut (AOP (result), "b", 0);
3635 /*-----------------------------------------------------------------*/
3636 /* genMod - generates code for division */
3637 /*-----------------------------------------------------------------*/
3641 operand *left = IC_LEFT (ic);
3642 operand *right = IC_RIGHT (ic);
3643 operand *result = IC_RESULT (ic);
3645 /* assign the amsops */
3646 aopOp (left, ic, FALSE);
3647 aopOp (right, ic, FALSE);
3648 aopOp (result, ic, TRUE);
3650 /* special cases first */
3652 if (AOP_TYPE (left) == AOP_CRY &&
3653 AOP_TYPE (right) == AOP_CRY)
3655 genModbits (left, right, result);
3659 /* if both are of size == 1 */
3660 if (AOP_SIZE (left) == 1 &&
3661 AOP_SIZE (right) == 1)
3663 genModOneByte (left, right, result);
3667 /* should have been converted to function call */
3671 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3672 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (result, NULL, ic, TRUE);
3676 /*-----------------------------------------------------------------*/
3677 /* genIfxJump :- will create a jump depending on the ifx */
3678 /*-----------------------------------------------------------------*/
3680 genIfxJump (iCode * ic, char *jval)
3683 symbol *tlbl = newiTempLabel (NULL);
3686 /* if true label then we jump if condition
3690 jlbl = IC_TRUE (ic);
3691 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3692 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3696 /* false label is present */
3697 jlbl = IC_FALSE (ic);
3698 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3699 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3701 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3702 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3704 emitcode (inst, "%05d$", tlbl->key + 100);
3705 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3706 emitcode ("", "%05d$:", tlbl->key + 100);
3708 /* mark the icode as generated */
3712 /*-----------------------------------------------------------------*/
3713 /* genCmp :- greater or less than comparison */
3714 /*-----------------------------------------------------------------*/
3716 genCmp (operand * left, operand * right,
3717 operand * result, iCode * ifx, int sign)
3719 int size, offset = 0;
3720 unsigned long lit = 0L;
3722 /* if left & right are bit variables */
3723 if (AOP_TYPE (left) == AOP_CRY &&
3724 AOP_TYPE (right) == AOP_CRY)
3726 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3727 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3731 /* subtract right from left if at the
3732 end the carry flag is set then we know that
3733 left is greater than right */
3734 size = max (AOP_SIZE (left), AOP_SIZE (right));
3736 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3737 if ((size == 1) && !sign &&
3738 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3740 symbol *lbl = newiTempLabel (NULL);
3741 emitcode ("cjne", "%s,%s,%05d$",
3742 aopGet (AOP (left), offset, FALSE, FALSE),
3743 aopGet (AOP (right), offset, FALSE, FALSE),
3745 emitcode ("", "%05d$:", lbl->key + 100);
3749 if (AOP_TYPE (right) == AOP_LIT)
3751 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3752 /* optimize if(x < 0) or if(x >= 0) */
3761 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3762 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3764 genIfxJump (ifx, "acc.7");
3768 emitcode ("rlc", "a");
3776 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3777 if (sign && size == 0)
3779 emitcode ("xrl", "a,#0x80");
3780 if (AOP_TYPE (right) == AOP_LIT)
3782 unsigned long lit = (unsigned long)
3783 floatFromVal (AOP (right)->aopu.aop_lit);
3784 emitcode ("subb", "a,#0x%02x",
3785 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3789 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3790 emitcode ("xrl", "b,#0x80");
3791 emitcode ("subb", "a,b");
3795 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3801 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3807 /* if the result is used in the next
3808 ifx conditional branch then generate
3809 code a little differently */
3811 genIfxJump (ifx, "c");
3814 /* leave the result in acc */
3818 /*-----------------------------------------------------------------*/
3819 /* genCmpGt :- greater than comparison */
3820 /*-----------------------------------------------------------------*/
3822 genCmpGt (iCode * ic, iCode * ifx)
3824 operand *left, *right, *result;
3825 sym_link *letype, *retype;
3828 left = IC_LEFT (ic);
3829 right = IC_RIGHT (ic);
3830 result = IC_RESULT (ic);
3832 letype = getSpec (operandType (left));
3833 retype = getSpec (operandType (right));
3834 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3835 /* assign the amsops */
3836 aopOp (left, ic, FALSE);
3837 aopOp (right, ic, FALSE);
3838 aopOp (result, ic, TRUE);
3840 genCmp (right, left, result, ifx, sign);
3842 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3843 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3844 freeAsmop (result, NULL, ic, TRUE);
3847 /*-----------------------------------------------------------------*/
3848 /* genCmpLt - less than comparisons */
3849 /*-----------------------------------------------------------------*/
3851 genCmpLt (iCode * ic, iCode * ifx)
3853 operand *left, *right, *result;
3854 sym_link *letype, *retype;
3857 left = IC_LEFT (ic);
3858 right = IC_RIGHT (ic);
3859 result = IC_RESULT (ic);
3861 letype = getSpec (operandType (left));
3862 retype = getSpec (operandType (right));
3863 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3865 /* assign the amsops */
3866 aopOp (left, ic, FALSE);
3867 aopOp (right, ic, FALSE);
3868 aopOp (result, ic, TRUE);
3870 genCmp (left, right, result, ifx, sign);
3872 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3873 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874 freeAsmop (result, NULL, ic, TRUE);
3877 /*-----------------------------------------------------------------*/
3878 /* gencjneshort - compare and jump if not equal */
3879 /*-----------------------------------------------------------------*/
3881 gencjneshort (operand * left, operand * right, symbol * lbl)
3883 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3885 unsigned long lit = 0L;
3887 /* if the left side is a literal or
3888 if the right is in a pointer register and left
3890 if ((AOP_TYPE (left) == AOP_LIT) ||
3891 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3897 if (AOP_TYPE (right) == AOP_LIT)
3898 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3900 /* if the right side is a literal then anything goes */
3901 if (AOP_TYPE (right) == AOP_LIT &&
3902 AOP_TYPE (left) != AOP_DIR)
3906 emitcode ("cjne", "%s,%s,%05d$",
3907 aopGet (AOP (left), offset, FALSE, FALSE),
3908 aopGet (AOP (right), offset, FALSE, FALSE),
3914 /* if the right side is in a register or in direct space or
3915 if the left is a pointer register & right is not */
3916 else if (AOP_TYPE (right) == AOP_REG ||
3917 AOP_TYPE (right) == AOP_DIR ||
3918 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3919 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3923 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3924 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3925 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3926 emitcode ("jnz", "%05d$", lbl->key + 100);
3928 emitcode ("cjne", "a,%s,%05d$",
3929 aopGet (AOP (right), offset, FALSE, TRUE),
3936 /* right is a pointer reg need both a & b */
3939 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3940 if (strcmp (l, "b"))
3941 emitcode ("mov", "b,%s", l);
3942 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3943 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3949 /*-----------------------------------------------------------------*/
3950 /* gencjne - compare and jump if not equal */
3951 /*-----------------------------------------------------------------*/
3953 gencjne (operand * left, operand * right, symbol * lbl)
3955 symbol *tlbl = newiTempLabel (NULL);
3957 gencjneshort (left, right, lbl);
3959 emitcode ("mov", "a,%s", one);
3960 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3961 emitcode ("", "%05d$:", lbl->key + 100);
3962 emitcode ("clr", "a");
3963 emitcode ("", "%05d$:", tlbl->key + 100);
3966 /*-----------------------------------------------------------------*/
3967 /* genCmpEq - generates code for equal to */
3968 /*-----------------------------------------------------------------*/
3970 genCmpEq (iCode * ic, iCode * ifx)
3972 operand *left, *right, *result;
3974 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3975 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3976 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3978 /* if literal, literal on the right or
3979 if the right is in a pointer register and left
3981 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3982 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3984 operand *t = IC_RIGHT (ic);
3985 IC_RIGHT (ic) = IC_LEFT (ic);
3989 if (ifx && !AOP_SIZE (result))
3992 /* if they are both bit variables */
3993 if (AOP_TYPE (left) == AOP_CRY &&
3994 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3996 if (AOP_TYPE (right) == AOP_LIT)
3998 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4001 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4002 emitcode ("cpl", "c");
4006 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4010 emitcode ("clr", "c");
4012 /* AOP_TYPE(right) == AOP_CRY */
4016 symbol *lbl = newiTempLabel (NULL);
4017 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4018 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4019 emitcode ("cpl", "c");
4020 emitcode ("", "%05d$:", (lbl->key + 100));
4022 /* if true label then we jump if condition
4024 tlbl = newiTempLabel (NULL);
4027 emitcode ("jnc", "%05d$", tlbl->key + 100);
4028 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4032 emitcode ("jc", "%05d$", tlbl->key + 100);
4033 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4035 emitcode ("", "%05d$:", tlbl->key + 100);
4039 tlbl = newiTempLabel (NULL);
4040 gencjneshort (left, right, tlbl);
4043 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4044 emitcode ("", "%05d$:", tlbl->key + 100);
4048 symbol *lbl = newiTempLabel (NULL);
4049 emitcode ("sjmp", "%05d$", lbl->key + 100);
4050 emitcode ("", "%05d$:", tlbl->key + 100);
4051 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4052 emitcode ("", "%05d$:", lbl->key + 100);
4055 /* mark the icode as generated */
4060 /* if they are both bit variables */
4061 if (AOP_TYPE (left) == AOP_CRY &&
4062 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4064 if (AOP_TYPE (right) == AOP_LIT)
4066 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4069 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4070 emitcode ("cpl", "c");
4074 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4078 emitcode ("clr", "c");
4080 /* AOP_TYPE(right) == AOP_CRY */
4084 symbol *lbl = newiTempLabel (NULL);
4085 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4086 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4087 emitcode ("cpl", "c");
4088 emitcode ("", "%05d$:", (lbl->key + 100));
4091 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4098 genIfxJump (ifx, "c");
4101 /* if the result is used in an arithmetic operation
4102 then put the result in place */
4107 gencjne (left, right, newiTempLabel (NULL));
4108 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4110 aopPut (AOP (result), "a", 0);
4115 genIfxJump (ifx, "a");
4118 /* if the result is used in an arithmetic operation
4119 then put the result in place */
4120 if (AOP_TYPE (result) != AOP_CRY)
4122 /* leave the result in acc */
4126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (result, NULL, ic, TRUE);
4131 /*-----------------------------------------------------------------*/
4132 /* ifxForOp - returns the icode containing the ifx for operand */
4133 /*-----------------------------------------------------------------*/
4135 ifxForOp (operand * op, iCode * ic)
4137 /* if true symbol then needs to be assigned */
4138 if (IS_TRUE_SYMOP (op))
4141 /* if this has register type condition and
4142 the next instruction is ifx with the same operand
4143 and live to of the operand is upto the ifx only then */
4145 ic->next->op == IFX &&
4146 IC_COND (ic->next)->key == op->key &&
4147 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4153 /*-----------------------------------------------------------------*/
4154 /* hasInc - operand is incremented before any other use */
4155 /*-----------------------------------------------------------------*/
4157 hasInc (operand *op, iCode *ic)
4159 sym_link *type = operandType(op);
4160 sym_link *retype = getSpec (type);
4161 iCode *lic = ic->next;
4164 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4165 isize = getSize(type->next);
4167 /* if operand of the form op = op + <sizeof *op> */
4168 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4169 isOperandEqual(IC_RESULT(lic),op) &&
4170 isOperandLiteral(IC_RIGHT(lic)) &&
4171 operandLitValue(IC_RIGHT(lic)) == isize) {
4174 /* if the operand used or deffed */
4175 if (bitVectBitValue(ic->uses,op->key) || ic->defKey == op->key) {
4183 /*-----------------------------------------------------------------*/
4184 /* genAndOp - for && operation */
4185 /*-----------------------------------------------------------------*/
4187 genAndOp (iCode * ic)
4189 operand *left, *right, *result;
4192 /* note here that && operations that are in an
4193 if statement are taken away by backPatchLabels
4194 only those used in arthmetic operations remain */
4195 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4196 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4197 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4199 /* if both are bit variables */
4200 if (AOP_TYPE (left) == AOP_CRY &&
4201 AOP_TYPE (right) == AOP_CRY)
4203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4204 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4209 tlbl = newiTempLabel (NULL);
4211 emitcode ("jz", "%05d$", tlbl->key + 100);
4213 emitcode ("", "%05d$:", tlbl->key + 100);
4217 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 freeAsmop (result, NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* genOrOp - for || operation */
4225 /*-----------------------------------------------------------------*/
4227 genOrOp (iCode * ic)
4229 operand *left, *right, *result;
4232 /* note here that || operations that are in an
4233 if statement are taken away by backPatchLabels
4234 only those used in arthmetic operations remain */
4235 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4236 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4237 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4239 /* if both are bit variables */
4240 if (AOP_TYPE (left) == AOP_CRY &&
4241 AOP_TYPE (right) == AOP_CRY)
4243 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4244 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4249 tlbl = newiTempLabel (NULL);
4251 emitcode ("jnz", "%05d$", tlbl->key + 100);
4253 emitcode ("", "%05d$:", tlbl->key + 100);
4257 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4259 freeAsmop (result, NULL, ic, TRUE);
4262 /*-----------------------------------------------------------------*/
4263 /* isLiteralBit - test if lit == 2^n */
4264 /*-----------------------------------------------------------------*/
4266 isLiteralBit (unsigned long lit)
4268 unsigned long pw[32] =
4269 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4270 0x100L, 0x200L, 0x400L, 0x800L,
4271 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4272 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4273 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4274 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4275 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4278 for (idx = 0; idx < 32; idx++)
4284 /*-----------------------------------------------------------------*/
4285 /* continueIfTrue - */
4286 /*-----------------------------------------------------------------*/
4288 continueIfTrue (iCode * ic)
4291 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4295 /*-----------------------------------------------------------------*/
4297 /*-----------------------------------------------------------------*/
4299 jumpIfTrue (iCode * ic)
4302 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4306 /*-----------------------------------------------------------------*/
4307 /* jmpTrueOrFalse - */
4308 /*-----------------------------------------------------------------*/
4310 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4312 // ugly but optimized by peephole
4315 symbol *nlbl = newiTempLabel (NULL);
4316 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4317 emitcode ("", "%05d$:", tlbl->key + 100);
4318 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4319 emitcode ("", "%05d$:", nlbl->key + 100);
4323 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4324 emitcode ("", "%05d$:", tlbl->key + 100);
4329 /*-----------------------------------------------------------------*/
4330 /* genAnd - code for and */
4331 /*-----------------------------------------------------------------*/
4333 genAnd (iCode * ic, iCode * ifx)
4335 operand *left, *right, *result;
4336 int size, offset = 0;
4337 unsigned long lit = 0L;
4341 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4342 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4343 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4346 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4348 AOP_TYPE (left), AOP_TYPE (right));
4349 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4351 AOP_SIZE (left), AOP_SIZE (right));
4354 /* if left is a literal & right is not then exchange them */
4355 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4356 AOP_NEEDSACC (left))
4358 operand *tmp = right;
4363 /* if result = right then exchange them */
4364 if (sameRegs (AOP (result), AOP (right)))
4366 operand *tmp = right;
4371 /* if right is bit then exchange them */
4372 if (AOP_TYPE (right) == AOP_CRY &&
4373 AOP_TYPE (left) != AOP_CRY)
4375 operand *tmp = right;
4379 if (AOP_TYPE (right) == AOP_LIT)
4380 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4382 size = AOP_SIZE (result);
4385 // result = bit & yy;
4386 if (AOP_TYPE (left) == AOP_CRY)
4388 // c = bit & literal;
4389 if (AOP_TYPE (right) == AOP_LIT)
4393 if (size && sameRegs (AOP (result), AOP (left)))
4396 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4401 if (size && (AOP_TYPE (result) == AOP_CRY))
4403 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4406 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4411 emitcode ("clr", "c");
4416 if (AOP_TYPE (right) == AOP_CRY)
4419 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4420 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4425 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4427 emitcode ("rrc", "a");
4428 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4436 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4437 genIfxJump (ifx, "c");
4441 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4442 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4443 if ((AOP_TYPE (right) == AOP_LIT) &&
4444 (AOP_TYPE (result) == AOP_CRY) &&
4445 (AOP_TYPE (left) != AOP_CRY))
4447 int posbit = isLiteralBit (lit);
4452 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4455 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4461 sprintf (buffer, "acc.%d", posbit & 0x07);
4462 genIfxJump (ifx, buffer);
4469 symbol *tlbl = newiTempLabel (NULL);
4470 int sizel = AOP_SIZE (left);
4472 emitcode ("setb", "c");
4475 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4477 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4479 if ((posbit = isLiteralBit (bytelit)) != 0)
4480 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4483 if (bytelit != 0x0FFL)
4484 emitcode ("anl", "a,%s",
4485 aopGet (AOP (right), offset, FALSE, TRUE));
4486 emitcode ("jnz", "%05d$", tlbl->key + 100);
4491 // bit = left & literal
4494 emitcode ("clr", "c");
4495 emitcode ("", "%05d$:", tlbl->key + 100);
4497 // if(left & literal)
4501 jmpTrueOrFalse (ifx, tlbl);
4509 /* if left is same as result */
4510 if (sameRegs (AOP (result), AOP (left)))
4512 for (; size--; offset++)
4514 if (AOP_TYPE (right) == AOP_LIT)
4516 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4518 else if (bytelit == 0)
4519 aopPut (AOP (result), zero, offset);
4520 else if (IS_AOP_PREG (result))
4522 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4523 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4524 aopPut (AOP (result), "a", offset);
4527 emitcode ("anl", "%s,%s",
4528 aopGet (AOP (left), offset, FALSE, TRUE),
4529 aopGet (AOP (right), offset, FALSE, FALSE));
4533 if (AOP_TYPE (left) == AOP_ACC)
4534 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4537 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4538 if (IS_AOP_PREG (result))
4540 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4541 aopPut (AOP (result), "a", offset);
4545 emitcode ("anl", "%s,a",
4546 aopGet (AOP (left), offset, FALSE, TRUE));
4553 // left & result in different registers
4554 if (AOP_TYPE (result) == AOP_CRY)
4557 // if(size), result in bit
4558 // if(!size && ifx), conditional oper: if(left & right)
4559 symbol *tlbl = newiTempLabel (NULL);
4560 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4562 emitcode ("setb", "c");
4565 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4566 emitcode ("anl", "a,%s",
4567 aopGet (AOP (left), offset, FALSE, FALSE));
4568 emitcode ("jnz", "%05d$", tlbl->key + 100);
4574 emitcode ("", "%05d$:", tlbl->key + 100);
4578 jmpTrueOrFalse (ifx, tlbl);
4582 for (; (size--); offset++)
4585 // result = left & right
4586 if (AOP_TYPE (right) == AOP_LIT)
4588 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4590 aopPut (AOP (result),
4591 aopGet (AOP (left), offset, FALSE, FALSE),
4595 else if (bytelit == 0)
4597 aopPut (AOP (result), zero, offset);
4601 // faster than result <- left, anl result,right
4602 // and better if result is SFR
4603 if (AOP_TYPE (left) == AOP_ACC)
4604 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4607 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4608 emitcode ("anl", "a,%s",
4609 aopGet (AOP (left), offset, FALSE, FALSE));
4611 aopPut (AOP (result), "a", offset);
4617 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4619 freeAsmop (result, NULL, ic, TRUE);
4622 /*-----------------------------------------------------------------*/
4623 /* genOr - code for or */
4624 /*-----------------------------------------------------------------*/
4626 genOr (iCode * ic, iCode * ifx)
4628 operand *left, *right, *result;
4629 int size, offset = 0;
4630 unsigned long lit = 0L;
4632 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4633 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4634 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4637 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4639 AOP_TYPE (left), AOP_TYPE (right));
4640 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4642 AOP_SIZE (left), AOP_SIZE (right));
4645 /* if left is a literal & right is not then exchange them */
4646 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4647 AOP_NEEDSACC (left))
4649 operand *tmp = right;
4654 /* if result = right then exchange them */
4655 if (sameRegs (AOP (result), AOP (right)))
4657 operand *tmp = right;
4662 /* if right is bit then exchange them */
4663 if (AOP_TYPE (right) == AOP_CRY &&
4664 AOP_TYPE (left) != AOP_CRY)
4666 operand *tmp = right;
4670 if (AOP_TYPE (right) == AOP_LIT)
4671 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4673 size = AOP_SIZE (result);
4677 if (AOP_TYPE (left) == AOP_CRY)
4679 if (AOP_TYPE (right) == AOP_LIT)
4681 // c = bit & literal;
4684 // lit != 0 => result = 1
4685 if (AOP_TYPE (result) == AOP_CRY)
4688 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4690 continueIfTrue (ifx);
4693 emitcode ("setb", "c");
4697 // lit == 0 => result = left
4698 if (size && sameRegs (AOP (result), AOP (left)))
4700 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4705 if (AOP_TYPE (right) == AOP_CRY)
4708 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4709 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4714 symbol *tlbl = newiTempLabel (NULL);
4715 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4716 emitcode ("setb", "c");
4717 emitcode ("jb", "%s,%05d$",
4718 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4720 emitcode ("jnz", "%05d$", tlbl->key + 100);
4721 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4723 jmpTrueOrFalse (ifx, tlbl);
4729 emitcode ("", "%05d$:", tlbl->key + 100);
4738 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4739 genIfxJump (ifx, "c");
4743 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4744 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4745 if ((AOP_TYPE (right) == AOP_LIT) &&
4746 (AOP_TYPE (result) == AOP_CRY) &&
4747 (AOP_TYPE (left) != AOP_CRY))
4753 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4755 continueIfTrue (ifx);
4760 // lit = 0, result = boolean(left)
4762 emitcode ("setb", "c");
4766 symbol *tlbl = newiTempLabel (NULL);
4767 emitcode ("jnz", "%05d$", tlbl->key + 100);
4769 emitcode ("", "%05d$:", tlbl->key + 100);
4773 genIfxJump (ifx, "a");
4781 /* if left is same as result */
4782 if (sameRegs (AOP (result), AOP (left)))
4784 for (; size--; offset++)
4786 if (AOP_TYPE (right) == AOP_LIT)
4788 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4790 else if (IS_AOP_PREG (left))
4792 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4793 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4794 aopPut (AOP (result), "a", offset);
4797 emitcode ("orl", "%s,%s",
4798 aopGet (AOP (left), offset, FALSE, TRUE),
4799 aopGet (AOP (right), offset, FALSE, FALSE));
4803 if (AOP_TYPE (left) == AOP_ACC)
4804 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4807 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4808 if (IS_AOP_PREG (left))
4810 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4811 aopPut (AOP (result), "a", offset);
4814 emitcode ("orl", "%s,a",
4815 aopGet (AOP (left), offset, FALSE, TRUE));
4822 // left & result in different registers
4823 if (AOP_TYPE (result) == AOP_CRY)
4826 // if(size), result in bit
4827 // if(!size && ifx), conditional oper: if(left | right)
4828 symbol *tlbl = newiTempLabel (NULL);
4829 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4831 emitcode ("setb", "c");
4834 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4835 emitcode ("orl", "a,%s",
4836 aopGet (AOP (left), offset, FALSE, FALSE));
4837 emitcode ("jnz", "%05d$", tlbl->key + 100);
4843 emitcode ("", "%05d$:", tlbl->key + 100);
4847 jmpTrueOrFalse (ifx, tlbl);
4850 for (; (size--); offset++)
4853 // result = left & right
4854 if (AOP_TYPE (right) == AOP_LIT)
4856 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4858 aopPut (AOP (result),
4859 aopGet (AOP (left), offset, FALSE, FALSE),
4864 // faster than result <- left, anl result,right
4865 // and better if result is SFR
4866 if (AOP_TYPE (left) == AOP_ACC)
4867 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4871 emitcode ("orl", "a,%s",
4872 aopGet (AOP (left), offset, FALSE, FALSE));
4874 aopPut (AOP (result), "a", offset);
4879 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4880 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4881 freeAsmop (result, NULL, ic, TRUE);
4884 /*-----------------------------------------------------------------*/
4885 /* genXor - code for xclusive or */
4886 /*-----------------------------------------------------------------*/
4888 genXor (iCode * ic, iCode * ifx)
4890 operand *left, *right, *result;
4891 int size, offset = 0;
4892 unsigned long lit = 0L;
4894 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4895 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4896 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4899 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4901 AOP_TYPE (left), AOP_TYPE (right));
4902 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4904 AOP_SIZE (left), AOP_SIZE (right));
4907 /* if left is a literal & right is not ||
4908 if left needs acc & right does not */
4909 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4910 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4912 operand *tmp = right;
4917 /* if result = right then exchange them */
4918 if (sameRegs (AOP (result), AOP (right)))
4920 operand *tmp = right;
4925 /* if right is bit then exchange them */
4926 if (AOP_TYPE (right) == AOP_CRY &&
4927 AOP_TYPE (left) != AOP_CRY)
4929 operand *tmp = right;
4933 if (AOP_TYPE (right) == AOP_LIT)
4934 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4936 size = AOP_SIZE (result);
4940 if (AOP_TYPE (left) == AOP_CRY)
4942 if (AOP_TYPE (right) == AOP_LIT)
4944 // c = bit & literal;
4947 // lit>>1 != 0 => result = 1
4948 if (AOP_TYPE (result) == AOP_CRY)
4951 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4953 continueIfTrue (ifx);
4956 emitcode ("setb", "c");
4963 // lit == 0, result = left
4964 if (size && sameRegs (AOP (result), AOP (left)))
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4970 // lit == 1, result = not(left)
4971 if (size && sameRegs (AOP (result), AOP (left)))
4973 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4978 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4979 emitcode ("cpl", "c");
4988 symbol *tlbl = newiTempLabel (NULL);
4989 if (AOP_TYPE (right) == AOP_CRY)
4992 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4996 int sizer = AOP_SIZE (right);
4998 // if val>>1 != 0, result = 1
4999 emitcode ("setb", "c");
5002 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5004 // test the msb of the lsb
5005 emitcode ("anl", "a,#0xfe");
5006 emitcode ("jnz", "%05d$", tlbl->key + 100);
5010 emitcode ("rrc", "a");
5012 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5013 emitcode ("cpl", "c");
5014 emitcode ("", "%05d$:", (tlbl->key + 100));
5021 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5022 genIfxJump (ifx, "c");
5026 if (sameRegs (AOP (result), AOP (left)))
5028 /* if left is same as result */
5029 for (; size--; offset++)
5031 if (AOP_TYPE (right) == AOP_LIT)
5033 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5035 else if (IS_AOP_PREG (left))
5037 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5038 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5039 aopPut (AOP (result), "a", offset);
5042 emitcode ("xrl", "%s,%s",
5043 aopGet (AOP (left), offset, FALSE, TRUE),
5044 aopGet (AOP (right), offset, FALSE, FALSE));
5048 if (AOP_TYPE (left) == AOP_ACC)
5049 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5052 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5053 if (IS_AOP_PREG (left))
5055 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5056 aopPut (AOP (result), "a", offset);
5059 emitcode ("xrl", "%s,a",
5060 aopGet (AOP (left), offset, FALSE, TRUE));
5067 // left & result in different registers
5068 if (AOP_TYPE (result) == AOP_CRY)
5071 // if(size), result in bit
5072 // if(!size && ifx), conditional oper: if(left ^ right)
5073 symbol *tlbl = newiTempLabel (NULL);
5074 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5076 emitcode ("setb", "c");
5079 if ((AOP_TYPE (right) == AOP_LIT) &&
5080 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5082 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5086 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5087 emitcode ("xrl", "a,%s",
5088 aopGet (AOP (left), offset, FALSE, FALSE));
5090 emitcode ("jnz", "%05d$", tlbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5100 jmpTrueOrFalse (ifx, tlbl);
5103 for (; (size--); offset++)
5106 // result = left & right
5107 if (AOP_TYPE (right) == AOP_LIT)
5109 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5111 aopPut (AOP (result),
5112 aopGet (AOP (left), offset, FALSE, FALSE),
5117 // faster than result <- left, anl result,right
5118 // and better if result is SFR
5119 if (AOP_TYPE (left) == AOP_ACC)
5120 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5123 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5124 emitcode ("xrl", "a,%s",
5125 aopGet (AOP (left), offset, FALSE, TRUE));
5127 aopPut (AOP (result), "a", offset);
5132 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 freeAsmop (result, NULL, ic, TRUE);
5137 /*-----------------------------------------------------------------*/
5138 /* genInline - write the inline code out */
5139 /*-----------------------------------------------------------------*/
5141 genInline (iCode * ic)
5143 char buffer[MAX_INLINEASM];
5147 _G.inLine += (!options.asmpeep);
5148 strcpy (buffer, IC_INLINE (ic));
5150 /* emit each line as a code */
5175 /* emitcode("",buffer); */
5176 _G.inLine -= (!options.asmpeep);
5179 /*-----------------------------------------------------------------*/
5180 /* genRRC - rotate right with carry */
5181 /*-----------------------------------------------------------------*/
5185 operand *left, *result;
5186 int size, offset = 0;
5189 /* rotate right with carry */
5190 left = IC_LEFT (ic);
5191 result = IC_RESULT (ic);
5192 aopOp (left, ic, FALSE);
5193 aopOp (result, ic, FALSE);
5195 /* move it to the result */
5196 size = AOP_SIZE (result);
5201 l = aopGet (AOP (left), offset, FALSE, FALSE);
5203 emitcode ("rrc", "a");
5204 if (AOP_SIZE (result) > 1)
5205 aopPut (AOP (result), "a", offset--);
5207 /* now we need to put the carry into the
5208 highest order byte of the result */
5209 if (AOP_SIZE (result) > 1)
5211 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5214 emitcode ("mov", "acc.7,c");
5215 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5216 freeAsmop (left, NULL, ic, TRUE);
5217 freeAsmop (result, NULL, ic, TRUE);
5220 /*-----------------------------------------------------------------*/
5221 /* genRLC - generate code for rotate left with carry */
5222 /*-----------------------------------------------------------------*/
5226 operand *left, *result;
5227 int size, offset = 0;
5230 /* rotate right with carry */
5231 left = IC_LEFT (ic);
5232 result = IC_RESULT (ic);
5233 aopOp (left, ic, FALSE);
5234 aopOp (result, ic, FALSE);
5236 /* move it to the result */
5237 size = AOP_SIZE (result);
5241 l = aopGet (AOP (left), offset, FALSE, FALSE);
5243 emitcode ("add", "a,acc");
5244 if (AOP_SIZE (result) > 1)
5245 aopPut (AOP (result), "a", offset++);
5248 l = aopGet (AOP (left), offset, FALSE, FALSE);
5250 emitcode ("rlc", "a");
5251 if (AOP_SIZE (result) > 1)
5252 aopPut (AOP (result), "a", offset++);
5255 /* now we need to put the carry into the
5256 highest order byte of the result */
5257 if (AOP_SIZE (result) > 1)
5259 l = aopGet (AOP (result), 0, FALSE, FALSE);
5262 emitcode ("mov", "acc.0,c");
5263 aopPut (AOP (result), "a", 0);
5264 freeAsmop (left, NULL, ic, TRUE);
5265 freeAsmop (result, NULL, ic, TRUE);
5268 /*-----------------------------------------------------------------*/
5269 /* genGetHbit - generates code get highest order bit */
5270 /*-----------------------------------------------------------------*/
5272 genGetHbit (iCode * ic)
5274 operand *left, *result;
5275 left = IC_LEFT (ic);
5276 result = IC_RESULT (ic);
5277 aopOp (left, ic, FALSE);
5278 aopOp (result, ic, FALSE);
5280 /* get the highest order byte into a */
5281 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5282 if (AOP_TYPE (result) == AOP_CRY)
5284 emitcode ("rlc", "a");
5289 emitcode ("rl", "a");
5290 emitcode ("anl", "a,#0x01");
5295 freeAsmop (left, NULL, ic, TRUE);
5296 freeAsmop (result, NULL, ic, TRUE);
5299 /*-----------------------------------------------------------------*/
5300 /* AccRol - rotate left accumulator by known count */
5301 /*-----------------------------------------------------------------*/
5303 AccRol (int shCount)
5305 shCount &= 0x0007; // shCount : 0..7
5312 emitcode ("rl", "a");
5315 emitcode ("rl", "a");
5316 emitcode ("rl", "a");
5319 emitcode ("swap", "a");
5320 emitcode ("rr", "a");
5323 emitcode ("swap", "a");
5326 emitcode ("swap", "a");
5327 emitcode ("rl", "a");
5330 emitcode ("rr", "a");
5331 emitcode ("rr", "a");
5334 emitcode ("rr", "a");
5339 /*-----------------------------------------------------------------*/
5340 /* AccLsh - left shift accumulator by known count */
5341 /*-----------------------------------------------------------------*/
5343 AccLsh (int shCount)
5348 emitcode ("add", "a,acc");
5349 else if (shCount == 2)
5351 emitcode ("add", "a,acc");
5352 emitcode ("add", "a,acc");
5356 /* rotate left accumulator */
5358 /* and kill the lower order bits */
5359 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5364 /*-----------------------------------------------------------------*/
5365 /* AccRsh - right shift accumulator by known count */
5366 /*-----------------------------------------------------------------*/
5368 AccRsh (int shCount)
5375 emitcode ("rrc", "a");
5379 /* rotate right accumulator */
5380 AccRol (8 - shCount);
5381 /* and kill the higher order bits */
5382 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5387 /*-----------------------------------------------------------------*/
5388 /* AccSRsh - signed right shift accumulator by known count */
5389 /*-----------------------------------------------------------------*/
5391 AccSRsh (int shCount)
5398 emitcode ("mov", "c,acc.7");
5399 emitcode ("rrc", "a");
5401 else if (shCount == 2)
5403 emitcode ("mov", "c,acc.7");
5404 emitcode ("rrc", "a");
5405 emitcode ("mov", "c,acc.7");
5406 emitcode ("rrc", "a");
5410 tlbl = newiTempLabel (NULL);
5411 /* rotate right accumulator */
5412 AccRol (8 - shCount);
5413 /* and kill the higher order bits */
5414 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5415 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5416 emitcode ("orl", "a,#0x%02x",
5417 (unsigned char) ~SRMask[shCount]);
5418 emitcode ("", "%05d$:", tlbl->key + 100);
5423 /*-----------------------------------------------------------------*/
5424 /* shiftR1Left2Result - shift right one byte from left to result */
5425 /*-----------------------------------------------------------------*/
5427 shiftR1Left2Result (operand * left, int offl,
5428 operand * result, int offr,
5429 int shCount, int sign)
5431 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5432 /* shift right accumulator */
5437 aopPut (AOP (result), "a", offr);
5440 /*-----------------------------------------------------------------*/
5441 /* shiftL1Left2Result - shift left one byte from left to result */
5442 /*-----------------------------------------------------------------*/
5444 shiftL1Left2Result (operand * left, int offl,
5445 operand * result, int offr, int shCount)
5448 l = aopGet (AOP (left), offl, FALSE, FALSE);
5450 /* shift left accumulator */
5452 aopPut (AOP (result), "a", offr);
5455 /*-----------------------------------------------------------------*/
5456 /* movLeft2Result - move byte from left to result */
5457 /*-----------------------------------------------------------------*/
5459 movLeft2Result (operand * left, int offl,
5460 operand * result, int offr, int sign)
5463 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5465 l = aopGet (AOP (left), offl, FALSE, FALSE);
5467 if (*l == '@' && (IS_AOP_PREG (result)))
5469 emitcode ("mov", "a,%s", l);
5470 aopPut (AOP (result), "a", offr);
5475 aopPut (AOP (result), l, offr);
5478 /* MSB sign in acc.7 ! */
5479 if (getDataSize (left) == offl + 1)
5481 emitcode ("mov", "a,%s", l);
5482 aopPut (AOP (result), "a", offr);
5489 /*-----------------------------------------------------------------*/
5490 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5491 /*-----------------------------------------------------------------*/
5495 emitcode ("rrc", "a");
5496 emitcode ("xch", "a,%s", x);
5497 emitcode ("rrc", "a");
5498 emitcode ("xch", "a,%s", x);
5501 /*-----------------------------------------------------------------*/
5502 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5503 /*-----------------------------------------------------------------*/
5507 emitcode ("xch", "a,%s", x);
5508 emitcode ("rlc", "a");
5509 emitcode ("xch", "a,%s", x);
5510 emitcode ("rlc", "a");
5513 /*-----------------------------------------------------------------*/
5514 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5515 /*-----------------------------------------------------------------*/
5519 emitcode ("xch", "a,%s", x);
5520 emitcode ("add", "a,acc");
5521 emitcode ("xch", "a,%s", x);
5522 emitcode ("rlc", "a");
5525 /*-----------------------------------------------------------------*/
5526 /* AccAXLsh - left shift a:x by known count (0..7) */
5527 /*-----------------------------------------------------------------*/
5529 AccAXLsh (char *x, int shCount)
5544 case 5: // AAAAABBB:CCCCCDDD
5546 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5548 emitcode ("anl", "a,#0x%02x",
5549 SLMask[shCount]); // BBB00000:CCCCCDDD
5551 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5553 AccRol (shCount); // DDDCCCCC:BBB00000
5555 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5557 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5559 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5561 emitcode ("anl", "a,#0x%02x",
5562 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5564 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5566 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5569 case 6: // AAAAAABB:CCCCCCDD
5570 emitcode ("anl", "a,#0x%02x",
5571 SRMask[shCount]); // 000000BB:CCCCCCDD
5572 emitcode ("mov", "c,acc.0"); // c = B
5573 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5575 AccAXRrl1 (x); // BCCCCCCD:D000000B
5576 AccAXRrl1 (x); // BBCCCCCC:DD000000
5578 emitcode("rrc","a");
5579 emitcode("xch","a,%s", x);
5580 emitcode("rrc","a");
5581 emitcode("mov","c,acc.0"); //<< get correct bit
5582 emitcode("xch","a,%s", x);
5584 emitcode("rrc","a");
5585 emitcode("xch","a,%s", x);
5586 emitcode("rrc","a");
5587 emitcode("xch","a,%s", x);
5590 case 7: // a:x <<= 7
5592 emitcode ("anl", "a,#0x%02x",
5593 SRMask[shCount]); // 0000000B:CCCCCCCD
5595 emitcode ("mov", "c,acc.0"); // c = B
5597 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5599 AccAXRrl1 (x); // BCCCCCCC:D0000000
5607 /*-----------------------------------------------------------------*/
5608 /* AccAXRsh - right shift a:x known count (0..7) */
5609 /*-----------------------------------------------------------------*/
5611 AccAXRsh (char *x, int shCount)
5619 AccAXRrl1 (x); // 0->a:x
5624 AccAXRrl1 (x); // 0->a:x
5627 AccAXRrl1 (x); // 0->a:x
5632 case 5: // AAAAABBB:CCCCCDDD = a:x
5634 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5636 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5638 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5640 emitcode ("anl", "a,#0x%02x",
5641 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5643 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5645 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5647 emitcode ("anl", "a,#0x%02x",
5648 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5650 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5652 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5654 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5657 case 6: // AABBBBBB:CCDDDDDD
5659 emitcode ("mov", "c,acc.7");
5660 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5662 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5664 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5666 emitcode ("anl", "a,#0x%02x",
5667 SRMask[shCount]); // 000000AA:BBBBBBCC
5670 case 7: // ABBBBBBB:CDDDDDDD
5672 emitcode ("mov", "c,acc.7"); // c = A
5674 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5676 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5678 emitcode ("anl", "a,#0x%02x",
5679 SRMask[shCount]); // 0000000A:BBBBBBBC
5687 /*-----------------------------------------------------------------*/
5688 /* AccAXRshS - right shift signed a:x known count (0..7) */
5689 /*-----------------------------------------------------------------*/
5691 AccAXRshS (char *x, int shCount)
5699 emitcode ("mov", "c,acc.7");
5700 AccAXRrl1 (x); // s->a:x
5704 emitcode ("mov", "c,acc.7");
5705 AccAXRrl1 (x); // s->a:x
5707 emitcode ("mov", "c,acc.7");
5708 AccAXRrl1 (x); // s->a:x
5713 case 5: // AAAAABBB:CCCCCDDD = a:x
5715 tlbl = newiTempLabel (NULL);
5716 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5718 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5720 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5722 emitcode ("anl", "a,#0x%02x",
5723 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5725 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5727 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5729 emitcode ("anl", "a,#0x%02x",
5730 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5732 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5734 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5736 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5738 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5739 emitcode ("orl", "a,#0x%02x",
5740 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5742 emitcode ("", "%05d$:", tlbl->key + 100);
5743 break; // SSSSAAAA:BBBCCCCC
5745 case 6: // AABBBBBB:CCDDDDDD
5747 tlbl = newiTempLabel (NULL);
5748 emitcode ("mov", "c,acc.7");
5749 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5751 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5753 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5755 emitcode ("anl", "a,#0x%02x",
5756 SRMask[shCount]); // 000000AA:BBBBBBCC
5758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5759 emitcode ("orl", "a,#0x%02x",
5760 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5762 emitcode ("", "%05d$:", tlbl->key + 100);
5764 case 7: // ABBBBBBB:CDDDDDDD
5766 tlbl = newiTempLabel (NULL);
5767 emitcode ("mov", "c,acc.7"); // c = A
5769 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5771 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5773 emitcode ("anl", "a,#0x%02x",
5774 SRMask[shCount]); // 0000000A:BBBBBBBC
5776 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5777 emitcode ("orl", "a,#0x%02x",
5778 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5780 emitcode ("", "%05d$:", tlbl->key + 100);
5787 /*-----------------------------------------------------------------*/
5788 /* shiftL2Left2Result - shift left two bytes from left to result */
5789 /*-----------------------------------------------------------------*/
5791 shiftL2Left2Result (operand * left, int offl,
5792 operand * result, int offr, int shCount)
5794 if (sameRegs (AOP (result), AOP (left)) &&
5795 ((offl + MSB16) == offr))
5797 /* don't crash result[offr] */
5798 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5799 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5803 movLeft2Result (left, offl, result, offr, 0);
5804 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5806 /* ax << shCount (x = lsb(result)) */
5807 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5808 aopPut (AOP (result), "a", offr + MSB16);
5812 /*-----------------------------------------------------------------*/
5813 /* shiftR2Left2Result - shift right two bytes from left to result */
5814 /*-----------------------------------------------------------------*/
5816 shiftR2Left2Result (operand * left, int offl,
5817 operand * result, int offr,
5818 int shCount, int sign)
5820 if (sameRegs (AOP (result), AOP (left)) &&
5821 ((offl + MSB16) == offr))
5823 /* don't crash result[offr] */
5824 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5825 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5829 movLeft2Result (left, offl, result, offr, 0);
5830 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5832 /* a:x >> shCount (x = lsb(result)) */
5834 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5836 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5837 if (getDataSize (result) > 1)
5838 aopPut (AOP (result), "a", offr + MSB16);
5841 /*-----------------------------------------------------------------*/
5842 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5843 /*-----------------------------------------------------------------*/
5845 shiftLLeftOrResult (operand * left, int offl,
5846 operand * result, int offr, int shCount)
5848 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5849 /* shift left accumulator */
5851 /* or with result */
5852 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5853 /* back to result */
5854 aopPut (AOP (result), "a", offr);
5857 /*-----------------------------------------------------------------*/
5858 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5859 /*-----------------------------------------------------------------*/
5861 shiftRLeftOrResult (operand * left, int offl,
5862 operand * result, int offr, int shCount)
5864 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5865 /* shift right accumulator */
5867 /* or with result */
5868 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5869 /* back to result */
5870 aopPut (AOP (result), "a", offr);
5873 /*-----------------------------------------------------------------*/
5874 /* genlshOne - left shift a one byte quantity by known count */
5875 /*-----------------------------------------------------------------*/
5877 genlshOne (operand * result, operand * left, int shCount)
5879 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5882 /*-----------------------------------------------------------------*/
5883 /* genlshTwo - left shift two bytes by known amount != 0 */
5884 /*-----------------------------------------------------------------*/
5886 genlshTwo (operand * result, operand * left, int shCount)
5890 size = getDataSize (result);
5892 /* if shCount >= 8 */
5900 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5902 movLeft2Result (left, LSB, result, MSB16, 0);
5904 aopPut (AOP (result), zero, LSB);
5907 /* 1 <= shCount <= 7 */
5911 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5913 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5917 /*-----------------------------------------------------------------*/
5918 /* shiftLLong - shift left one long from left to result */
5919 /* offl = LSB or MSB16 */
5920 /*-----------------------------------------------------------------*/
5922 shiftLLong (operand * left, operand * result, int offr)
5925 int size = AOP_SIZE (result);
5927 if (size >= LSB + offr)
5929 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5931 emitcode ("add", "a,acc");
5932 if (sameRegs (AOP (left), AOP (result)) &&
5933 size >= MSB16 + offr && offr != LSB)
5934 emitcode ("xch", "a,%s",
5935 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5937 aopPut (AOP (result), "a", LSB + offr);
5940 if (size >= MSB16 + offr)
5942 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5944 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5947 emitcode ("rlc", "a");
5948 if (sameRegs (AOP (left), AOP (result)) &&
5949 size >= MSB24 + offr && offr != LSB)
5950 emitcode ("xch", "a,%s",
5951 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5953 aopPut (AOP (result), "a", MSB16 + offr);
5956 if (size >= MSB24 + offr)
5958 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5960 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5963 emitcode ("rlc", "a");
5964 if (sameRegs (AOP (left), AOP (result)) &&
5965 size >= MSB32 + offr && offr != LSB)
5966 emitcode ("xch", "a,%s",
5967 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5969 aopPut (AOP (result), "a", MSB24 + offr);
5972 if (size > MSB32 + offr)
5974 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5976 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5979 emitcode ("rlc", "a");
5980 aopPut (AOP (result), "a", MSB32 + offr);
5983 aopPut (AOP (result), zero, LSB);
5986 /*-----------------------------------------------------------------*/
5987 /* genlshFour - shift four byte by a known amount != 0 */
5988 /*-----------------------------------------------------------------*/
5990 genlshFour (operand * result, operand * left, int shCount)
5994 size = AOP_SIZE (result);
5996 /* if shifting more that 3 bytes */
6001 /* lowest order of left goes to the highest
6002 order of the destination */
6003 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6005 movLeft2Result (left, LSB, result, MSB32, 0);
6006 aopPut (AOP (result), zero, LSB);
6007 aopPut (AOP (result), zero, MSB16);
6008 aopPut (AOP (result), zero, MSB32);
6012 /* more than two bytes */
6013 else if (shCount >= 16)
6015 /* lower order two bytes goes to higher order two bytes */
6017 /* if some more remaining */
6019 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6022 movLeft2Result (left, MSB16, result, MSB32, 0);
6023 movLeft2Result (left, LSB, result, MSB24, 0);
6025 aopPut (AOP (result), zero, MSB16);
6026 aopPut (AOP (result), zero, LSB);
6030 /* if more than 1 byte */
6031 else if (shCount >= 8)
6033 /* lower order three bytes goes to higher order three bytes */
6038 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6040 movLeft2Result (left, LSB, result, MSB16, 0);
6046 movLeft2Result (left, MSB24, result, MSB32, 0);
6047 movLeft2Result (left, MSB16, result, MSB24, 0);
6048 movLeft2Result (left, LSB, result, MSB16, 0);
6049 aopPut (AOP (result), zero, LSB);
6051 else if (shCount == 1)
6052 shiftLLong (left, result, MSB16);
6055 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6056 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6057 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6058 aopPut (AOP (result), zero, LSB);
6063 /* 1 <= shCount <= 7 */
6064 else if (shCount <= 2)
6066 shiftLLong (left, result, LSB);
6068 shiftLLong (result, result, LSB);
6070 /* 3 <= shCount <= 7, optimize */
6073 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6074 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6075 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6079 /*-----------------------------------------------------------------*/
6080 /* genLeftShiftLiteral - left shifting by known count */
6081 /*-----------------------------------------------------------------*/
6083 genLeftShiftLiteral (operand * left,
6088 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6091 freeAsmop (right, NULL, ic, TRUE);
6093 aopOp (left, ic, FALSE);
6094 aopOp (result, ic, FALSE);
6096 size = getSize (operandType (result));
6099 emitcode ("; shift left ", "result %d, left %d", size,
6103 /* I suppose that the left size >= result size */
6108 movLeft2Result (left, size, result, size, 0);
6112 else if (shCount >= (size * 8))
6114 aopPut (AOP (result), zero, size);
6120 genlshOne (result, left, shCount);
6125 genlshTwo (result, left, shCount);
6129 genlshFour (result, left, shCount);
6133 freeAsmop (left, NULL, ic, TRUE);
6134 freeAsmop (result, NULL, ic, TRUE);
6137 /*-----------------------------------------------------------------*/
6138 /* genLeftShift - generates code for left shifting */
6139 /*-----------------------------------------------------------------*/
6141 genLeftShift (iCode * ic)
6143 operand *left, *right, *result;
6146 symbol *tlbl, *tlbl1;
6148 right = IC_RIGHT (ic);
6149 left = IC_LEFT (ic);
6150 result = IC_RESULT (ic);
6152 aopOp (right, ic, FALSE);
6154 /* if the shift count is known then do it
6155 as efficiently as possible */
6156 if (AOP_TYPE (right) == AOP_LIT)
6158 genLeftShiftLiteral (left, right, result, ic);
6162 /* shift count is unknown then we have to form
6163 a loop get the loop count in B : Note: we take
6164 only the lower order byte since shifting
6165 more that 32 bits make no sense anyway, ( the
6166 largest size of an object can be only 32 bits ) */
6168 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6169 emitcode ("inc", "b");
6170 freeAsmop (right, NULL, ic, TRUE);
6171 aopOp (left, ic, FALSE);
6172 aopOp (result, ic, FALSE);
6174 /* now move the left to the result if they are not the
6176 if (!sameRegs (AOP (left), AOP (result)) &&
6177 AOP_SIZE (result) > 1)
6180 size = AOP_SIZE (result);
6184 l = aopGet (AOP (left), offset, FALSE, TRUE);
6185 if (*l == '@' && (IS_AOP_PREG (result)))
6188 emitcode ("mov", "a,%s", l);
6189 aopPut (AOP (result), "a", offset);
6192 aopPut (AOP (result), l, offset);
6197 tlbl = newiTempLabel (NULL);
6198 size = AOP_SIZE (result);
6200 tlbl1 = newiTempLabel (NULL);
6202 /* if it is only one byte then */
6205 symbol *tlbl1 = newiTempLabel (NULL);
6207 l = aopGet (AOP (left), 0, FALSE, FALSE);
6209 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6210 emitcode ("", "%05d$:", tlbl->key + 100);
6211 emitcode ("add", "a,acc");
6212 emitcode ("", "%05d$:", tlbl1->key + 100);
6213 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6214 aopPut (AOP (result), "a", 0);
6218 reAdjustPreg (AOP (result));
6220 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6221 emitcode ("", "%05d$:", tlbl->key + 100);
6222 l = aopGet (AOP (result), offset, FALSE, FALSE);
6224 emitcode ("add", "a,acc");
6225 aopPut (AOP (result), "a", offset++);
6228 l = aopGet (AOP (result), offset, FALSE, FALSE);
6230 emitcode ("rlc", "a");
6231 aopPut (AOP (result), "a", offset++);
6233 reAdjustPreg (AOP (result));
6235 emitcode ("", "%05d$:", tlbl1->key + 100);
6236 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6238 freeAsmop (left, NULL, ic, TRUE);
6239 freeAsmop (result, NULL, ic, TRUE);
6242 /*-----------------------------------------------------------------*/
6243 /* genrshOne - right shift a one byte quantity by known count */
6244 /*-----------------------------------------------------------------*/
6246 genrshOne (operand * result, operand * left,
6247 int shCount, int sign)
6249 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6252 /*-----------------------------------------------------------------*/
6253 /* genrshTwo - right shift two bytes by known amount != 0 */
6254 /*-----------------------------------------------------------------*/
6256 genrshTwo (operand * result, operand * left,
6257 int shCount, int sign)
6259 /* if shCount >= 8 */
6264 shiftR1Left2Result (left, MSB16, result, LSB,
6267 movLeft2Result (left, MSB16, result, LSB, sign);
6268 addSign (result, MSB16, sign);
6271 /* 1 <= shCount <= 7 */
6273 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6276 /*-----------------------------------------------------------------*/
6277 /* shiftRLong - shift right one long from left to result */
6278 /* offl = LSB or MSB16 */
6279 /*-----------------------------------------------------------------*/
6281 shiftRLong (operand * left, int offl,
6282 operand * result, int sign)
6285 emitcode ("clr", "c");
6286 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6288 emitcode ("mov", "c,acc.7");
6289 emitcode ("rrc", "a");
6290 aopPut (AOP (result), "a", MSB32 - offl);
6292 /* add sign of "a" */
6293 addSign (result, MSB32, sign);
6295 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6296 emitcode ("rrc", "a");
6297 aopPut (AOP (result), "a", MSB24 - offl);
6299 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6300 emitcode ("rrc", "a");
6301 aopPut (AOP (result), "a", MSB16 - offl);
6305 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6306 emitcode ("rrc", "a");
6307 aopPut (AOP (result), "a", LSB);
6311 /*-----------------------------------------------------------------*/
6312 /* genrshFour - shift four byte by a known amount != 0 */
6313 /*-----------------------------------------------------------------*/
6315 genrshFour (operand * result, operand * left,
6316 int shCount, int sign)
6318 /* if shifting more that 3 bytes */
6323 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6325 movLeft2Result (left, MSB32, result, LSB, sign);
6326 addSign (result, MSB16, sign);
6328 else if (shCount >= 16)
6332 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6335 movLeft2Result (left, MSB24, result, LSB, 0);
6336 movLeft2Result (left, MSB32, result, MSB16, sign);
6338 addSign (result, MSB24, sign);
6340 else if (shCount >= 8)
6344 shiftRLong (left, MSB16, result, sign);
6345 else if (shCount == 0)
6347 movLeft2Result (left, MSB16, result, LSB, 0);
6348 movLeft2Result (left, MSB24, result, MSB16, 0);
6349 movLeft2Result (left, MSB32, result, MSB24, sign);
6350 addSign (result, MSB32, sign);
6354 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6355 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6356 /* the last shift is signed */
6357 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6358 addSign (result, MSB32, sign);
6362 { /* 1 <= shCount <= 7 */
6365 shiftRLong (left, LSB, result, sign);
6367 shiftRLong (result, LSB, result, sign);
6371 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6372 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6373 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6378 /*-----------------------------------------------------------------*/
6379 /* genRightShiftLiteral - right shifting by known count */
6380 /*-----------------------------------------------------------------*/
6382 genRightShiftLiteral (operand * left,
6388 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6391 freeAsmop (right, NULL, ic, TRUE);
6393 aopOp (left, ic, FALSE);
6394 aopOp (result, ic, FALSE);
6397 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6401 size = getDataSize (left);
6402 /* test the LEFT size !!! */
6404 /* I suppose that the left size >= result size */
6407 size = getDataSize (result);
6409 movLeft2Result (left, size, result, size, 0);
6412 else if (shCount >= (size * 8))
6415 /* get sign in acc.7 */
6416 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6417 addSign (result, LSB, sign);
6424 genrshOne (result, left, shCount, sign);
6428 genrshTwo (result, left, shCount, sign);
6432 genrshFour (result, left, shCount, sign);
6438 freeAsmop (left, NULL, ic, TRUE);
6439 freeAsmop (result, NULL, ic, TRUE);
6443 /*-----------------------------------------------------------------*/
6444 /* genSignedRightShift - right shift of signed number */
6445 /*-----------------------------------------------------------------*/
6447 genSignedRightShift (iCode * ic)
6449 operand *right, *left, *result;
6452 symbol *tlbl, *tlbl1;
6454 /* we do it the hard way put the shift count in b
6455 and loop thru preserving the sign */
6457 right = IC_RIGHT (ic);
6458 left = IC_LEFT (ic);
6459 result = IC_RESULT (ic);
6461 aopOp (right, ic, FALSE);
6464 if (AOP_TYPE (right) == AOP_LIT)
6466 genRightShiftLiteral (left, right, result, ic, 1);
6469 /* shift count is unknown then we have to form
6470 a loop get the loop count in B : Note: we take
6471 only the lower order byte since shifting
6472 more that 32 bits make no sense anyway, ( the
6473 largest size of an object can be only 32 bits ) */
6475 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6476 emitcode ("inc", "b");
6477 freeAsmop (right, NULL, ic, TRUE);
6478 aopOp (left, ic, FALSE);
6479 aopOp (result, ic, FALSE);
6481 /* now move the left to the result if they are not the
6483 if (!sameRegs (AOP (left), AOP (result)) &&
6484 AOP_SIZE (result) > 1)
6487 size = AOP_SIZE (result);
6491 l = aopGet (AOP (left), offset, FALSE, TRUE);
6492 if (*l == '@' && IS_AOP_PREG (result))
6495 emitcode ("mov", "a,%s", l);
6496 aopPut (AOP (result), "a", offset);
6499 aopPut (AOP (result), l, offset);
6504 /* mov the highest order bit to OVR */
6505 tlbl = newiTempLabel (NULL);
6506 tlbl1 = newiTempLabel (NULL);
6508 size = AOP_SIZE (result);
6510 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6511 emitcode ("rlc", "a");
6512 emitcode ("mov", "ov,c");
6513 /* if it is only one byte then */
6516 l = aopGet (AOP (left), 0, FALSE, FALSE);
6518 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6519 emitcode ("", "%05d$:", tlbl->key + 100);
6520 emitcode ("mov", "c,ov");
6521 emitcode ("rrc", "a");
6522 emitcode ("", "%05d$:", tlbl1->key + 100);
6523 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6524 aopPut (AOP (result), "a", 0);
6528 reAdjustPreg (AOP (result));
6529 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6530 emitcode ("", "%05d$:", tlbl->key + 100);
6531 emitcode ("mov", "c,ov");
6534 l = aopGet (AOP (result), offset, FALSE, FALSE);
6536 emitcode ("rrc", "a");
6537 aopPut (AOP (result), "a", offset--);
6539 reAdjustPreg (AOP (result));
6540 emitcode ("", "%05d$:", tlbl1->key + 100);
6541 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6544 freeAsmop (left, NULL, ic, TRUE);
6545 freeAsmop (result, NULL, ic, TRUE);
6548 /*-----------------------------------------------------------------*/
6549 /* genRightShift - generate code for right shifting */
6550 /*-----------------------------------------------------------------*/
6552 genRightShift (iCode * ic)
6554 operand *right, *left, *result;
6558 symbol *tlbl, *tlbl1;
6560 /* if signed then we do it the hard way preserve the
6561 sign bit moving it inwards */
6562 retype = getSpec (operandType (IC_RESULT (ic)));
6564 if (!SPEC_USIGN (retype))
6566 genSignedRightShift (ic);
6570 /* signed & unsigned types are treated the same : i.e. the
6571 signed is NOT propagated inwards : quoting from the
6572 ANSI - standard : "for E1 >> E2, is equivalent to division
6573 by 2**E2 if unsigned or if it has a non-negative value,
6574 otherwise the result is implementation defined ", MY definition
6575 is that the sign does not get propagated */
6577 right = IC_RIGHT (ic);
6578 left = IC_LEFT (ic);
6579 result = IC_RESULT (ic);
6581 aopOp (right, ic, FALSE);
6583 /* if the shift count is known then do it
6584 as efficiently as possible */
6585 if (AOP_TYPE (right) == AOP_LIT)
6587 genRightShiftLiteral (left, right, result, ic, 0);
6591 /* shift count is unknown then we have to form
6592 a loop get the loop count in B : Note: we take
6593 only the lower order byte since shifting
6594 more that 32 bits make no sense anyway, ( the
6595 largest size of an object can be only 32 bits ) */
6597 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6598 emitcode ("inc", "b");
6599 freeAsmop (right, NULL, ic, TRUE);
6600 aopOp (left, ic, FALSE);
6601 aopOp (result, ic, FALSE);
6603 /* now move the left to the result if they are not the
6605 if (!sameRegs (AOP (left), AOP (result)) &&
6606 AOP_SIZE (result) > 1)
6609 size = AOP_SIZE (result);
6613 l = aopGet (AOP (left), offset, FALSE, TRUE);
6614 if (*l == '@' && IS_AOP_PREG (result))
6617 emitcode ("mov", "a,%s", l);
6618 aopPut (AOP (result), "a", offset);
6621 aopPut (AOP (result), l, offset);
6626 tlbl = newiTempLabel (NULL);
6627 tlbl1 = newiTempLabel (NULL);
6628 size = AOP_SIZE (result);
6631 /* if it is only one byte then */
6634 l = aopGet (AOP (left), 0, FALSE, FALSE);
6636 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6637 emitcode ("", "%05d$:", tlbl->key + 100);
6639 emitcode ("rrc", "a");
6640 emitcode ("", "%05d$:", tlbl1->key + 100);
6641 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6642 aopPut (AOP (result), "a", 0);
6646 reAdjustPreg (AOP (result));
6647 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6648 emitcode ("", "%05d$:", tlbl->key + 100);
6652 l = aopGet (AOP (result), offset, FALSE, FALSE);
6654 emitcode ("rrc", "a");
6655 aopPut (AOP (result), "a", offset--);
6657 reAdjustPreg (AOP (result));
6659 emitcode ("", "%05d$:", tlbl1->key + 100);
6660 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6663 freeAsmop (left, NULL, ic, TRUE);
6664 freeAsmop (result, NULL, ic, TRUE);
6667 /*-----------------------------------------------------------------*/
6668 /* genUnpackBits - generates code for unpacking bits */
6669 /*-----------------------------------------------------------------*/
6671 genUnpackBits (operand * result, char *rname, int ptype)
6679 etype = getSpec (operandType (result));
6680 rsize = getSize (operandType (result));
6681 /* read the first byte */
6687 emitcode ("mov", "a,@%s", rname);
6691 emitcode ("movx", "a,@%s", rname);
6695 emitcode ("movx", "a,@dptr");
6699 emitcode ("clr", "a");
6700 emitcode ("movc", "a,%s", "@a+dptr");
6704 emitcode ("lcall", "__gptrget");
6708 rlen = SPEC_BLEN (etype);
6710 /* if we have bitdisplacement then it fits */
6711 /* into this byte completely or if length is */
6712 /* less than a byte */
6713 if ((shCnt = SPEC_BSTR (etype)) ||
6714 (SPEC_BLEN (etype) <= 8))
6717 /* shift right acc */
6720 emitcode ("anl", "a,#0x%02x",
6721 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6722 aopPut (AOP (result), "a", offset++);
6726 /* bit field did not fit in a byte */
6727 aopPut (AOP (result), "a", offset++);
6736 emitcode ("inc", "%s", rname);
6737 emitcode ("mov", "a,@%s", rname);
6741 emitcode ("inc", "%s", rname);
6742 emitcode ("movx", "a,@%s", rname);
6746 emitcode ("inc", "dptr");
6747 emitcode ("movx", "a,@dptr");
6751 emitcode ("clr", "a");
6752 emitcode ("inc", "dptr");
6753 emitcode ("movc", "a", "@a+dptr");
6757 emitcode ("inc", "dptr");
6758 emitcode ("lcall", "__gptrget");
6763 /* if we are done */
6767 aopPut (AOP (result), "a", offset++);
6773 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6775 aopPut (AOP (result), "a", offset++);
6783 aopPut (AOP (result), zero, offset++);
6789 /*-----------------------------------------------------------------*/
6790 /* genDataPointerGet - generates code when ptr offset is known */
6791 /*-----------------------------------------------------------------*/
6793 genDataPointerGet (operand * left,
6799 int size, offset = 0;
6800 aopOp (result, ic, TRUE);
6802 /* get the string representation of the name */
6803 l = aopGet (AOP (left), 0, FALSE, TRUE);
6804 size = AOP_SIZE (result);
6808 sprintf (buffer, "(%s + %d)", l + 1, offset);
6810 sprintf (buffer, "%s", l + 1);
6811 aopPut (AOP (result), buffer, offset++);
6814 freeAsmop (left, NULL, ic, TRUE);
6815 freeAsmop (result, NULL, ic, TRUE);
6818 /*-----------------------------------------------------------------*/
6819 /* genNearPointerGet - emitcode for near pointer fetch */
6820 /*-----------------------------------------------------------------*/
6822 genNearPointerGet (operand * left,
6830 sym_link *rtype, *retype;
6831 sym_link *ltype = operandType (left);
6834 rtype = operandType (result);
6835 retype = getSpec (rtype);
6837 aopOp (left, ic, FALSE);
6839 /* if left is rematerialisable and
6840 result is not bit variable type and
6841 the left is pointer to data space i.e
6842 lower 128 bytes of space */
6843 if (AOP_TYPE (left) == AOP_IMMD &&
6844 !IS_BITVAR (retype) &&
6845 DCL_TYPE (ltype) == POINTER)
6847 genDataPointerGet (left, result, ic);
6851 /* if the value is already in a pointer register
6852 then don't need anything more */
6853 if (!AOP_INPREG (AOP (left)))
6855 /* otherwise get a free pointer register */
6857 preg = getFreePtr (ic, &aop, FALSE);
6858 emitcode ("mov", "%s,%s",
6860 aopGet (AOP (left), 0, FALSE, TRUE));
6864 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6866 aopOp (result, ic, FALSE);
6868 /* if bitfield then unpack the bits */
6869 if (IS_BITVAR (retype))
6870 genUnpackBits (result, rname, POINTER);
6873 /* we have can just get the values */
6874 int size = AOP_SIZE (result);
6879 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6882 emitcode ("mov", "a,@%s", rname);
6883 aopPut (AOP (result), "a", offset);
6887 sprintf (buffer, "@%s", rname);
6888 aopPut (AOP (result), buffer, offset);
6892 emitcode ("inc", "%s", rname);
6896 /* now some housekeeping stuff */
6897 if (aop) /* we had to allocate for this iCode */
6899 if (pi) { /* post increment present */
6900 aopPut(AOP ( left ),rname,0);
6902 freeAsmop (NULL, aop, ic, TRUE);
6906 /* we did not allocate which means left
6907 already in a pointer register, then
6908 if size > 0 && this could be used again
6909 we have to point it back to where it
6911 if ((AOP_SIZE (result) > 1 &&
6912 !OP_SYMBOL (left)->remat &&
6913 (OP_SYMBOL (left)->liveTo > ic->seq ||
6917 int size = AOP_SIZE (result) - 1;
6919 emitcode ("dec", "%s", rname);
6924 freeAsmop (left, NULL, ic, TRUE);
6925 freeAsmop (result, NULL, ic, TRUE);
6926 if (pi) pi->generated = 1;
6929 /*-----------------------------------------------------------------*/
6930 /* genPagedPointerGet - emitcode for paged pointer fetch */
6931 /*-----------------------------------------------------------------*/
6933 genPagedPointerGet (operand * left,
6941 sym_link *rtype, *retype;
6943 rtype = operandType (result);
6944 retype = getSpec (rtype);
6946 aopOp (left, ic, FALSE);
6948 /* if the value is already in a pointer register
6949 then don't need anything more */
6950 if (!AOP_INPREG (AOP (left)))
6952 /* otherwise get a free pointer register */
6954 preg = getFreePtr (ic, &aop, FALSE);
6955 emitcode ("mov", "%s,%s",
6957 aopGet (AOP (left), 0, FALSE, TRUE));
6961 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6963 aopOp (result, ic, FALSE);
6965 /* if bitfield then unpack the bits */
6966 if (IS_BITVAR (retype))
6967 genUnpackBits (result, rname, PPOINTER);
6970 /* we have can just get the values */
6971 int size = AOP_SIZE (result);
6977 emitcode ("movx", "a,@%s", rname);
6978 aopPut (AOP (result), "a", offset);
6983 emitcode ("inc", "%s", rname);
6987 /* now some housekeeping stuff */
6988 if (aop) /* we had to allocate for this iCode */
6990 if (pi) aopPut ( AOP (left), rname, 0);
6991 freeAsmop (NULL, aop, ic, TRUE);
6995 /* we did not allocate which means left
6996 already in a pointer register, then
6997 if size > 0 && this could be used again
6998 we have to point it back to where it
7000 if ((AOP_SIZE (result) > 1 &&
7001 !OP_SYMBOL (left)->remat &&
7002 (OP_SYMBOL (left)->liveTo > ic->seq ||
7006 int size = AOP_SIZE (result) - 1;
7008 emitcode ("dec", "%s", rname);
7013 freeAsmop (left, NULL, ic, TRUE);
7014 freeAsmop (result, NULL, ic, TRUE);
7015 if (pi) pi->generated = 1;
7019 /*-----------------------------------------------------------------*/
7020 /* genFarPointerGet - gget value from far space */
7021 /*-----------------------------------------------------------------*/
7023 genFarPointerGet (operand * left,
7024 operand * result, iCode * ic, iCode * pi)
7027 sym_link *retype = getSpec (operandType (result));
7029 aopOp (left, ic, FALSE);
7031 /* if the operand is already in dptr
7032 then we do nothing else we move the value to dptr */
7033 if (AOP_TYPE (left) != AOP_STR)
7035 /* if this is remateriazable */
7036 if (AOP_TYPE (left) == AOP_IMMD)
7037 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7039 { /* we need to get it byte by byte */
7040 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7041 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7044 /* so dptr know contains the address */
7045 aopOp (result, ic, FALSE);
7047 /* if bit then unpack */
7048 if (IS_BITVAR (retype))
7049 genUnpackBits (result, "dptr", FPOINTER);
7052 size = AOP_SIZE (result);
7057 emitcode ("movx", "a,@dptr");
7058 aopPut (AOP (result), "a", offset++);
7060 emitcode ("inc", "dptr");
7064 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7065 aopPut ( AOP (left), "dpl", 0);
7066 aopPut ( AOP (left), "dph", 1);
7069 freeAsmop (left, NULL, ic, TRUE);
7070 freeAsmop (result, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genCodePointerGet - gget value from code space */
7075 /*-----------------------------------------------------------------*/
7077 genCodePointerGet (operand * left,
7078 operand * result, iCode * ic, iCode *pi)
7081 sym_link *retype = getSpec (operandType (result));
7083 aopOp (left, ic, FALSE);
7085 /* if the operand is already in dptr
7086 then we do nothing else we move the value to dptr */
7087 if (AOP_TYPE (left) != AOP_STR)
7089 /* if this is remateriazable */
7090 if (AOP_TYPE (left) == AOP_IMMD)
7091 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7093 { /* we need to get it byte by byte */
7094 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7095 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7098 /* so dptr know contains the address */
7099 aopOp (result, ic, FALSE);
7101 /* if bit then unpack */
7102 if (IS_BITVAR (retype))
7103 genUnpackBits (result, "dptr", CPOINTER);
7106 size = AOP_SIZE (result);
7111 emitcode ("clr", "a");
7112 emitcode ("movc", "a,@a+dptr");
7113 aopPut (AOP (result), "a", offset++);
7115 emitcode ("inc", "dptr");
7119 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7120 aopPut ( AOP (left), "dpl", 0);
7121 aopPut ( AOP (left), "dph", 1);
7124 freeAsmop (left, NULL, ic, TRUE);
7125 freeAsmop (result, NULL, ic, TRUE);
7128 /*-----------------------------------------------------------------*/
7129 /* genGenPointerGet - gget value from generic pointer space */
7130 /*-----------------------------------------------------------------*/
7132 genGenPointerGet (operand * left,
7133 operand * result, iCode * ic, iCode *pi)
7136 sym_link *retype = getSpec (operandType (result));
7138 aopOp (left, ic, FALSE);
7140 /* if the operand is already in dptr
7141 then we do nothing else we move the value to dptr */
7142 if (AOP_TYPE (left) != AOP_STR)
7144 /* if this is remateriazable */
7145 if (AOP_TYPE (left) == AOP_IMMD)
7147 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7148 emitcode ("mov", "b,#%d", pointerCode (retype));
7151 { /* we need to get it byte by byte */
7152 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7153 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7154 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7157 /* so dptr know contains the address */
7158 aopOp (result, ic, FALSE);
7160 /* if bit then unpack */
7161 if (IS_BITVAR (retype))
7162 genUnpackBits (result, "dptr", GPOINTER);
7165 size = AOP_SIZE (result);
7170 emitcode ("lcall", "__gptrget");
7171 aopPut (AOP (result), "a", offset++);
7173 emitcode ("inc", "dptr");
7177 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7178 aopPut ( AOP (left), "dpl", 0);
7179 aopPut ( AOP (left), "dph", 1);
7182 freeAsmop (left, NULL, ic, TRUE);
7183 freeAsmop (result, NULL, ic, TRUE);
7186 /*-----------------------------------------------------------------*/
7187 /* genPointerGet - generate code for pointer get */
7188 /*-----------------------------------------------------------------*/
7190 genPointerGet (iCode * ic, iCode *pi)
7192 operand *left, *result;
7193 sym_link *type, *etype;
7196 left = IC_LEFT (ic);
7197 result = IC_RESULT (ic);
7199 /* depending on the type of pointer we need to
7200 move it to the correct pointer register */
7201 type = operandType (left);
7202 etype = getSpec (type);
7203 /* if left is of type of pointer then it is simple */
7204 if (IS_PTR (type) && !IS_FUNC (type->next))
7205 p_type = DCL_TYPE (type);
7208 /* we have to go by the storage class */
7209 p_type = PTR_TYPE (SPEC_OCLS (etype));
7212 /* now that we have the pointer type we assign
7213 the pointer values */
7219 genNearPointerGet (left, result, ic, pi);
7223 genPagedPointerGet (left, result, ic, pi);
7227 genFarPointerGet (left, result, ic, pi);
7231 genCodePointerGet (left, result, ic, pi);
7235 genGenPointerGet (left, result, ic, pi);
7241 /*-----------------------------------------------------------------*/
7242 /* genPackBits - generates code for packed bit storage */
7243 /*-----------------------------------------------------------------*/
7245 genPackBits (sym_link * etype,
7247 char *rname, int p_type)
7255 blen = SPEC_BLEN (etype);
7256 bstr = SPEC_BSTR (etype);
7258 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7261 /* if the bit lenth is less than or */
7262 /* it exactly fits a byte then */
7263 if (SPEC_BLEN (etype) <= 8)
7265 shCount = SPEC_BSTR (etype);
7267 /* shift left acc */
7270 if (SPEC_BLEN (etype) < 8)
7271 { /* if smaller than a byte */
7277 emitcode ("mov", "b,a");
7278 emitcode ("mov", "a,@%s", rname);
7282 emitcode ("mov", "b,a");
7283 emitcode ("movx", "a,@dptr");
7287 emitcode ("push", "b");
7288 emitcode ("push", "acc");
7289 emitcode ("lcall", "__gptrget");
7290 emitcode ("pop", "b");
7294 emitcode ("anl", "a,#0x%02x", (unsigned char)
7295 ((unsigned char) (0xFF << (blen + bstr)) |
7296 (unsigned char) (0xFF >> (8 - bstr))));
7297 emitcode ("orl", "a,b");
7298 if (p_type == GPOINTER)
7299 emitcode ("pop", "b");
7306 emitcode ("mov", "@%s,a", rname);
7310 emitcode ("movx", "@dptr,a");
7314 emitcode ("lcall", "__gptrput");
7319 if (SPEC_BLEN (etype) <= 8)
7322 emitcode ("inc", "%s", rname);
7323 rLen = SPEC_BLEN (etype);
7325 /* now generate for lengths greater than one byte */
7329 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7341 emitcode ("mov", "@%s,a", rname);
7344 emitcode ("mov", "@%s,%s", rname, l);
7349 emitcode ("movx", "@dptr,a");
7354 emitcode ("lcall", "__gptrput");
7357 emitcode ("inc", "%s", rname);
7362 /* last last was not complete */
7365 /* save the byte & read byte */
7369 emitcode ("mov", "b,a");
7370 emitcode ("mov", "a,@%s", rname);
7374 emitcode ("mov", "b,a");
7375 emitcode ("movx", "a,@dptr");
7379 emitcode ("push", "b");
7380 emitcode ("push", "acc");
7381 emitcode ("lcall", "__gptrget");
7382 emitcode ("pop", "b");
7386 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7387 emitcode ("orl", "a,b");
7390 if (p_type == GPOINTER)
7391 emitcode ("pop", "b");
7397 emitcode ("mov", "@%s,a", rname);
7401 emitcode ("movx", "@dptr,a");
7405 emitcode ("lcall", "__gptrput");
7409 /*-----------------------------------------------------------------*/
7410 /* genDataPointerSet - remat pointer to data space */
7411 /*-----------------------------------------------------------------*/
7413 genDataPointerSet (operand * right,
7417 int size, offset = 0;
7418 char *l, buffer[256];
7420 aopOp (right, ic, FALSE);
7422 l = aopGet (AOP (result), 0, FALSE, TRUE);
7423 size = AOP_SIZE (right);
7427 sprintf (buffer, "(%s + %d)", l + 1, offset);
7429 sprintf (buffer, "%s", l + 1);
7430 emitcode ("mov", "%s,%s", buffer,
7431 aopGet (AOP (right), offset++, FALSE, FALSE));
7434 freeAsmop (right, NULL, ic, TRUE);
7435 freeAsmop (result, NULL, ic, TRUE);
7438 /*-----------------------------------------------------------------*/
7439 /* genNearPointerSet - emitcode for near pointer put */
7440 /*-----------------------------------------------------------------*/
7442 genNearPointerSet (operand * right,
7450 sym_link *retype, *letype;
7451 sym_link *ptype = operandType (result);
7453 retype = getSpec (operandType (right));
7454 letype = getSpec (ptype);
7455 aopOp (result, ic, FALSE);
7457 /* if the result is rematerializable &
7458 in data space & not a bit variable */
7459 if (AOP_TYPE (result) == AOP_IMMD &&
7460 DCL_TYPE (ptype) == POINTER &&
7461 !IS_BITVAR (retype) &&
7462 !IS_BITVAR (letype))
7464 genDataPointerSet (right, result, ic);
7468 /* if the value is already in a pointer register
7469 then don't need anything more */
7470 if (!AOP_INPREG (AOP (result)))
7472 /* otherwise get a free pointer register */
7474 preg = getFreePtr (ic, &aop, FALSE);
7475 emitcode ("mov", "%s,%s",
7477 aopGet (AOP (result), 0, FALSE, TRUE));
7481 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7483 aopOp (right, ic, FALSE);
7485 /* if bitfield then unpack the bits */
7486 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7487 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7490 /* we have can just get the values */
7491 int size = AOP_SIZE (right);
7496 l = aopGet (AOP (right), offset, FALSE, TRUE);
7500 emitcode ("mov", "@%s,a", rname);
7503 emitcode ("mov", "@%s,%s", rname, l);
7505 emitcode ("inc", "%s", rname);
7510 /* now some housekeeping stuff */
7511 if (aop) /* we had to allocate for this iCode */
7513 if (pi) aopPut (AOP (result),rname,0);
7514 freeAsmop (NULL, aop, ic, TRUE);
7518 /* we did not allocate which means left
7519 already in a pointer register, then
7520 if size > 0 && this could be used again
7521 we have to point it back to where it
7523 if ((AOP_SIZE (right) > 1 &&
7524 !OP_SYMBOL (result)->remat &&
7525 (OP_SYMBOL (result)->liveTo > ic->seq ||
7529 int size = AOP_SIZE (right) - 1;
7531 emitcode ("dec", "%s", rname);
7536 if (pi) pi->generated = 1;
7537 freeAsmop (result, NULL, ic, TRUE);
7538 freeAsmop (right, NULL, ic, TRUE);
7541 /*-----------------------------------------------------------------*/
7542 /* genPagedPointerSet - emitcode for Paged pointer put */
7543 /*-----------------------------------------------------------------*/
7545 genPagedPointerSet (operand * right,
7553 sym_link *retype, *letype;
7555 retype = getSpec (operandType (right));
7556 letype = getSpec (operandType (result));
7558 aopOp (result, ic, FALSE);
7560 /* if the value is already in a pointer register
7561 then don't need anything more */
7562 if (!AOP_INPREG (AOP (result)))
7564 /* otherwise get a free pointer register */
7566 preg = getFreePtr (ic, &aop, FALSE);
7567 emitcode ("mov", "%s,%s",
7569 aopGet (AOP (result), 0, FALSE, TRUE));
7573 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7575 aopOp (right, ic, FALSE);
7577 /* if bitfield then unpack the bits */
7578 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7579 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7582 /* we have can just get the values */
7583 int size = AOP_SIZE (right);
7588 l = aopGet (AOP (right), offset, FALSE, TRUE);
7591 emitcode ("movx", "@%s,a", rname);
7594 emitcode ("inc", "%s", rname);
7600 /* now some housekeeping stuff */
7601 if (aop) /* we had to allocate for this iCode */
7603 if (pi) aopPut (AOP (result),rname,0);
7604 freeAsmop (NULL, aop, ic, TRUE);
7608 /* we did not allocate which means left
7609 already in a pointer register, then
7610 if size > 0 && this could be used again
7611 we have to point it back to where it
7613 if (AOP_SIZE (right) > 1 &&
7614 !OP_SYMBOL (result)->remat &&
7615 (OP_SYMBOL (result)->liveTo > ic->seq ||
7618 int size = AOP_SIZE (right) - 1;
7620 emitcode ("dec", "%s", rname);
7625 if (pi) pi->generated = 1;
7626 freeAsmop (result, NULL, ic, TRUE);
7627 freeAsmop (right, NULL, ic, TRUE);
7632 /*-----------------------------------------------------------------*/
7633 /* genFarPointerSet - set value from far space */
7634 /*-----------------------------------------------------------------*/
7636 genFarPointerSet (operand * right,
7637 operand * result, iCode * ic, iCode * pi)
7640 sym_link *retype = getSpec (operandType (right));
7641 sym_link *letype = getSpec (operandType (result));
7642 aopOp (result, ic, FALSE);
7644 /* if the operand is already in dptr
7645 then we do nothing else we move the value to dptr */
7646 if (AOP_TYPE (result) != AOP_STR)
7648 /* if this is remateriazable */
7649 if (AOP_TYPE (result) == AOP_IMMD)
7650 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7652 { /* we need to get it byte by byte */
7653 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7654 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7657 /* so dptr know contains the address */
7658 aopOp (right, ic, FALSE);
7660 /* if bit then unpack */
7661 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7662 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7665 size = AOP_SIZE (right);
7670 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7672 emitcode ("movx", "@dptr,a");
7674 emitcode ("inc", "dptr");
7677 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7678 aopPut (AOP(result),"dpl",0);
7679 aopPut (AOP(result),"dph",1);
7682 freeAsmop (result, NULL, ic, TRUE);
7683 freeAsmop (right, NULL, ic, TRUE);
7686 /*-----------------------------------------------------------------*/
7687 /* genGenPointerSet - set value from generic pointer space */
7688 /*-----------------------------------------------------------------*/
7690 genGenPointerSet (operand * right,
7691 operand * result, iCode * ic, iCode * pi)
7694 sym_link *retype = getSpec (operandType (right));
7695 sym_link *letype = getSpec (operandType (result));
7697 aopOp (result, ic, FALSE);
7699 /* if the operand is already in dptr
7700 then we do nothing else we move the value to dptr */
7701 if (AOP_TYPE (result) != AOP_STR)
7703 /* if this is remateriazable */
7704 if (AOP_TYPE (result) == AOP_IMMD)
7706 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7707 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7710 { /* we need to get it byte by byte */
7711 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7712 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7713 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7716 /* so dptr know contains the address */
7717 aopOp (right, ic, FALSE);
7719 /* if bit then unpack */
7720 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7721 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7724 size = AOP_SIZE (right);
7729 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7731 emitcode ("lcall", "__gptrput");
7733 emitcode ("inc", "dptr");
7737 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7738 aopPut (AOP(result),"dpl",0);
7739 aopPut (AOP(result),"dph",1);
7742 freeAsmop (result, NULL, ic, TRUE);
7743 freeAsmop (right, NULL, ic, TRUE);
7746 /*-----------------------------------------------------------------*/
7747 /* genPointerSet - stores the value into a pointer location */
7748 /*-----------------------------------------------------------------*/
7750 genPointerSet (iCode * ic, iCode *pi)
7752 operand *right, *result;
7753 sym_link *type, *etype;
7756 right = IC_RIGHT (ic);
7757 result = IC_RESULT (ic);
7759 /* depending on the type of pointer we need to
7760 move it to the correct pointer register */
7761 type = operandType (result);
7762 etype = getSpec (type);
7763 /* if left is of type of pointer then it is simple */
7764 if (IS_PTR (type) && !IS_FUNC (type->next))
7766 p_type = DCL_TYPE (type);
7770 /* we have to go by the storage class */
7771 p_type = PTR_TYPE (SPEC_OCLS (etype));
7774 /* now that we have the pointer type we assign
7775 the pointer values */
7781 genNearPointerSet (right, result, ic, pi);
7785 genPagedPointerSet (right, result, ic, pi);
7789 genFarPointerSet (right, result, ic, pi);
7793 genGenPointerSet (right, result, ic, pi);
7799 /*-----------------------------------------------------------------*/
7800 /* genIfx - generate code for Ifx statement */
7801 /*-----------------------------------------------------------------*/
7803 genIfx (iCode * ic, iCode * popIc)
7805 operand *cond = IC_COND (ic);
7808 aopOp (cond, ic, FALSE);
7810 /* get the value into acc */
7811 if (AOP_TYPE (cond) != AOP_CRY)
7815 /* the result is now in the accumulator */
7816 freeAsmop (cond, NULL, ic, TRUE);
7818 /* if there was something to be popped then do it */
7822 /* if the condition is a bit variable */
7823 if (isbit && IS_ITEMP (cond) &&
7825 genIfxJump (ic, SPIL_LOC (cond)->rname);
7826 else if (isbit && !IS_ITEMP (cond))
7827 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7829 genIfxJump (ic, "a");
7834 /*-----------------------------------------------------------------*/
7835 /* genAddrOf - generates code for address of */
7836 /*-----------------------------------------------------------------*/
7838 genAddrOf (iCode * ic)
7840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7843 aopOp (IC_RESULT (ic), ic, FALSE);
7845 /* if the operand is on the stack then we
7846 need to get the stack offset of this
7850 /* if it has an offset then we need to compute
7854 emitcode ("mov", "a,_bp");
7855 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7856 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7860 /* we can just move _bp */
7861 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7863 /* fill the result with zero */
7864 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7869 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7875 /* object not on stack then we need the name */
7876 size = AOP_SIZE (IC_RESULT (ic));
7881 char s[SDCC_NAME_MAX];
7883 sprintf (s, "#(%s >> %d)",
7887 sprintf (s, "#%s", sym->rname);
7888 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7892 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7896 /*-----------------------------------------------------------------*/
7897 /* genFarFarAssign - assignment when both are in far space */
7898 /*-----------------------------------------------------------------*/
7900 genFarFarAssign (operand * result, operand * right, iCode * ic)
7902 int size = AOP_SIZE (right);
7905 /* first push the right side on to the stack */
7908 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7910 emitcode ("push", "acc");
7913 freeAsmop (right, NULL, ic, FALSE);
7914 /* now assign DPTR to result */
7915 aopOp (result, ic, FALSE);
7916 size = AOP_SIZE (result);
7919 emitcode ("pop", "acc");
7920 aopPut (AOP (result), "a", --offset);
7922 freeAsmop (result, NULL, ic, FALSE);
7926 /*-----------------------------------------------------------------*/
7927 /* genAssign - generate code for assignment */
7928 /*-----------------------------------------------------------------*/
7930 genAssign (iCode * ic)
7932 operand *result, *right;
7934 unsigned long lit = 0L;
7936 result = IC_RESULT (ic);
7937 right = IC_RIGHT (ic);
7939 /* if they are the same */
7940 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7943 aopOp (right, ic, FALSE);
7945 /* special case both in far space */
7946 if ((AOP_TYPE (right) == AOP_DPTR ||
7947 AOP_TYPE (right) == AOP_DPTR2) &&
7948 IS_TRUE_SYMOP (result) &&
7949 isOperandInFarSpace (result))
7952 genFarFarAssign (result, right, ic);
7956 aopOp (result, ic, TRUE);
7958 /* if they are the same registers */
7959 if (sameRegs (AOP (right), AOP (result)))
7962 /* if the result is a bit */
7963 if (AOP_TYPE (result) == AOP_CRY)
7966 /* if the right size is a literal then
7967 we know what the value is */
7968 if (AOP_TYPE (right) == AOP_LIT)
7970 if (((int) operandLitValue (right)))
7971 aopPut (AOP (result), one, 0);
7973 aopPut (AOP (result), zero, 0);
7977 /* the right is also a bit variable */
7978 if (AOP_TYPE (right) == AOP_CRY)
7980 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7981 aopPut (AOP (result), "c", 0);
7987 aopPut (AOP (result), "a", 0);
7991 /* bit variables done */
7993 size = AOP_SIZE (result);
7995 if (AOP_TYPE (right) == AOP_LIT)
7996 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7998 (AOP_TYPE (result) != AOP_REG) &&
7999 (AOP_TYPE (right) == AOP_LIT) &&
8000 !IS_FLOAT (operandType (right)) &&
8003 emitcode ("clr", "a");
8006 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8007 aopPut (AOP (result), "a", size);
8009 aopPut (AOP (result),
8010 aopGet (AOP (right), size, FALSE, FALSE),
8018 aopPut (AOP (result),
8019 aopGet (AOP (right), offset, FALSE, FALSE),
8026 freeAsmop (right, NULL, ic, TRUE);
8027 freeAsmop (result, NULL, ic, TRUE);
8030 /*-----------------------------------------------------------------*/
8031 /* genJumpTab - genrates code for jump table */
8032 /*-----------------------------------------------------------------*/
8034 genJumpTab (iCode * ic)
8039 aopOp (IC_JTCOND (ic), ic, FALSE);
8040 /* get the condition into accumulator */
8041 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8043 /* multiply by three */
8044 emitcode ("add", "a,acc");
8045 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8046 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8048 jtab = newiTempLabel (NULL);
8049 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8050 emitcode ("jmp", "@a+dptr");
8051 emitcode ("", "%05d$:", jtab->key + 100);
8052 /* now generate the jump labels */
8053 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8054 jtab = setNextItem (IC_JTLABELS (ic)))
8055 emitcode ("ljmp", "%05d$", jtab->key + 100);
8059 /*-----------------------------------------------------------------*/
8060 /* genCast - gen code for casting */
8061 /*-----------------------------------------------------------------*/
8063 genCast (iCode * ic)
8065 operand *result = IC_RESULT (ic);
8066 sym_link *ctype = operandType (IC_LEFT (ic));
8067 sym_link *rtype = operandType (IC_RIGHT (ic));
8068 operand *right = IC_RIGHT (ic);
8071 /* if they are equivalent then do nothing */
8072 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8075 aopOp (right, ic, FALSE);
8076 aopOp (result, ic, FALSE);
8078 /* if the result is a bit */
8079 if (AOP_TYPE (result) == AOP_CRY)
8081 /* if the right size is a literal then
8082 we know what the value is */
8083 if (AOP_TYPE (right) == AOP_LIT)
8085 if (((int) operandLitValue (right)))
8086 aopPut (AOP (result), one, 0);
8088 aopPut (AOP (result), zero, 0);
8093 /* the right is also a bit variable */
8094 if (AOP_TYPE (right) == AOP_CRY)
8096 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8097 aopPut (AOP (result), "c", 0);
8103 aopPut (AOP (result), "a", 0);
8107 /* if they are the same size : or less */
8108 if (AOP_SIZE (result) <= AOP_SIZE (right))
8111 /* if they are in the same place */
8112 if (sameRegs (AOP (right), AOP (result)))
8115 /* if they in different places then copy */
8116 size = AOP_SIZE (result);
8120 aopPut (AOP (result),
8121 aopGet (AOP (right), offset, FALSE, FALSE),
8129 /* if the result is of type pointer */
8134 sym_link *type = operandType (right);
8135 sym_link *etype = getSpec (type);
8137 /* pointer to generic pointer */
8138 if (IS_GENPTR (ctype))
8143 p_type = DCL_TYPE (type);
8146 /* we have to go by the storage class */
8147 p_type = PTR_TYPE (SPEC_OCLS (etype));
8150 /* the first two bytes are known */
8151 size = GPTRSIZE - 1;
8155 aopPut (AOP (result),
8156 aopGet (AOP (right), offset, FALSE, FALSE),
8160 /* the last byte depending on type */
8178 /* this should never happen */
8179 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8180 "got unknown pointer type");
8183 aopPut (AOP (result), l, GPTRSIZE - 1);
8187 /* just copy the pointers */
8188 size = AOP_SIZE (result);
8192 aopPut (AOP (result),
8193 aopGet (AOP (right), offset, FALSE, FALSE),
8200 /* so we now know that the size of destination is greater
8201 than the size of the source */
8202 /* we move to result for the size of source */
8203 size = AOP_SIZE (right);
8207 aopPut (AOP (result),
8208 aopGet (AOP (right), offset, FALSE, FALSE),
8213 /* now depending on the sign of the source && destination */
8214 size = AOP_SIZE (result) - AOP_SIZE (right);
8215 /* if unsigned or not an integral type */
8216 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8219 aopPut (AOP (result), zero, offset++);
8223 /* we need to extend the sign :{ */
8224 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8227 emitcode ("rlc", "a");
8228 emitcode ("subb", "a,acc");
8230 aopPut (AOP (result), "a", offset++);
8233 /* we are done hurray !!!! */
8236 freeAsmop (right, NULL, ic, TRUE);
8237 freeAsmop (result, NULL, ic, TRUE);
8241 /*-----------------------------------------------------------------*/
8242 /* genDjnz - generate decrement & jump if not zero instrucion */
8243 /*-----------------------------------------------------------------*/
8245 genDjnz (iCode * ic, iCode * ifx)
8251 /* if the if condition has a false label
8252 then we cannot save */
8256 /* if the minus is not of the form
8258 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8259 !IS_OP_LITERAL (IC_RIGHT (ic)))
8262 if (operandLitValue (IC_RIGHT (ic)) != 1)
8265 /* if the size of this greater than one then no
8267 if (getSize (operandType (IC_RESULT (ic))) > 1)
8270 /* otherwise we can save BIG */
8271 lbl = newiTempLabel (NULL);
8272 lbl1 = newiTempLabel (NULL);
8274 aopOp (IC_RESULT (ic), ic, FALSE);
8276 if (IS_AOP_PREG (IC_RESULT (ic)))
8278 emitcode ("dec", "%s",
8279 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8280 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8281 emitcode ("jnz", "%05d$", lbl->key + 100);
8285 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8288 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8289 emitcode ("", "%05d$:", lbl->key + 100);
8290 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8291 emitcode ("", "%05d$:", lbl1->key + 100);
8293 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8298 /*-----------------------------------------------------------------*/
8299 /* genReceive - generate code for a receive iCode */
8300 /*-----------------------------------------------------------------*/
8302 genReceive (iCode * ic)
8304 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8305 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8306 IS_TRUE_SYMOP (IC_RESULT (ic))))
8309 int size = getSize (operandType (IC_RESULT (ic)));
8310 int offset = fReturnSizeMCS51 - size;
8313 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8314 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8317 aopOp (IC_RESULT (ic), ic, FALSE);
8318 size = AOP_SIZE (IC_RESULT (ic));
8322 emitcode ("pop", "acc");
8323 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8330 aopOp (IC_RESULT (ic), ic, FALSE);
8332 assignResultValue (IC_RESULT (ic));
8335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8338 /*-----------------------------------------------------------------*/
8339 /* gen51Code - generate code for 8051 based controllers */
8340 /*-----------------------------------------------------------------*/
8342 gen51Code (iCode * lic)
8347 lineHead = lineCurr = NULL;
8349 /* print the allocation information */
8351 printAllocInfo (currFunc, codeOutFile);
8352 /* if debug information required */
8353 /* if (options.debug && currFunc) { */
8356 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8358 if (IS_STATIC (currFunc->etype))
8359 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8361 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8364 /* stack pointer name */
8365 if (options.useXstack)
8371 for (ic = lic; ic; ic = ic->next)
8374 if (cln != ic->lineno)
8379 emitcode ("", "C$%s$%d$%d$%d ==.",
8380 FileBaseName (ic->filename), ic->lineno,
8381 ic->level, ic->block);
8384 emitcode (";", "%s %d", ic->filename, ic->lineno);
8387 /* if the result is marked as
8388 spilt and rematerializable or code for
8389 this has already been generated then
8391 if (resultRemat (ic) || ic->generated)
8394 /* depending on the operation */
8414 /* IPOP happens only when trying to restore a
8415 spilt live range, if there is an ifx statement
8416 following this pop then the if statement might
8417 be using some of the registers being popped which
8418 would destory the contents of the register so
8419 we need to check for this condition and handle it */
8421 ic->next->op == IFX &&
8422 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8423 genIfx (ic->next, ic);
8441 genEndFunction (ic);
8461 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8478 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8482 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8489 /* note these two are xlated by algebraic equivalence
8490 during parsing SDCC.y */
8491 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8492 "got '>=' or '<=' shouldn't have come here");
8496 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8508 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8512 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8516 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8543 case GET_VALUE_AT_ADDRESS:
8544 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8548 if (POINTER_SET (ic))
8549 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8575 addSet (&_G.sendSet, ic);
8580 /* piCode(ic,stdout); */
8586 /* now we are ready to call the
8587 peep hole optimizer */
8588 if (!options.nopeep)
8589 peepHole (&lineHead);
8591 /* now do the actual printing */
8592 printLine (lineHead, codeOutFile);