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)
889 if (aop->size && offset > (aop->size - 1))
891 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
892 "aopPut got offset > aop->size");
896 /* will assign value to value */
897 /* depending on where it is ofcourse */
902 sprintf (d, "(%s + %d)",
903 aop->aopu.aop_dir, offset);
905 sprintf (d, "%s", aop->aopu.aop_dir);
908 emitcode ("mov", "%s,%s", d, s);
913 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
914 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
917 strcmp (s, "r0") == 0 ||
918 strcmp (s, "r1") == 0 ||
919 strcmp (s, "r2") == 0 ||
920 strcmp (s, "r3") == 0 ||
921 strcmp (s, "r4") == 0 ||
922 strcmp (s, "r5") == 0 ||
923 strcmp (s, "r6") == 0 ||
924 strcmp (s, "r7") == 0)
925 emitcode ("mov", "%s,%s",
926 aop->aopu.aop_reg[offset]->dname, s);
928 emitcode ("mov", "%s,%s",
929 aop->aopu.aop_reg[offset]->name, s);
936 if (aop->type == AOP_DPTR2)
943 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
944 "aopPut writting to code space");
948 while (offset > aop->coff)
951 emitcode ("inc", "dptr");
954 while (offset < aop->coff)
957 emitcode ("lcall", "__decdptr");
962 /* if not in accumulater */
965 emitcode ("movx", "@dptr,a");
967 if (aop->type == AOP_DPTR2)
975 while (offset > aop->coff)
978 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
980 while (offset < aop->coff)
983 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
990 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
996 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
998 else if (strcmp (s, "r0") == 0 ||
999 strcmp (s, "r1") == 0 ||
1000 strcmp (s, "r2") == 0 ||
1001 strcmp (s, "r3") == 0 ||
1002 strcmp (s, "r4") == 0 ||
1003 strcmp (s, "r5") == 0 ||
1004 strcmp (s, "r6") == 0 ||
1005 strcmp (s, "r7") == 0)
1008 sprintf (buffer, "a%s", s);
1009 emitcode ("mov", "@%s,%s",
1010 aop->aopu.aop_ptr->name, buffer);
1013 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1018 if (strcmp (s, "a") == 0)
1019 emitcode ("push", "acc");
1021 emitcode ("push", "%s", s);
1026 /* if bit variable */
1027 if (!aop->aopu.aop_dir)
1029 emitcode ("clr", "a");
1030 emitcode ("rlc", "a");
1035 emitcode ("clr", "%s", aop->aopu.aop_dir);
1037 emitcode ("setb", "%s", aop->aopu.aop_dir);
1038 else if (!strcmp (s, "c"))
1039 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1042 lbl = newiTempLabel (NULL);
1044 if (strcmp (s, "a"))
1048 emitcode ("clr", "c");
1049 emitcode ("jz", "%05d$", lbl->key + 100);
1050 emitcode ("cpl", "c");
1051 emitcode ("", "%05d$:", lbl->key + 100);
1052 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
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));
1186 tlbl = newiTempLabel (NULL);
1188 tlbl = newiTempLabel (NULL);
1189 aopPut (res->aop, one, 1);
1190 emitcode ("jz", "%05d$", (tlbl->key + 100));
1191 aopPut (res->aop, zero, 1);
1192 emitcode ("", "%05d$:", (tlbl->key + 100));
1194 size = res->aop->size - 2;
1196 /* put zeros in the rest */
1198 aopPut (res->aop, zero, offset++);
1201 /*-----------------------------------------------------------------*/
1202 /* opIsGptr: returns non-zero if the passed operand is */
1203 /* a generic pointer type. */
1204 /*-----------------------------------------------------------------*/
1206 opIsGptr (operand * op)
1208 sym_link *type = operandType (op);
1210 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1217 /*-----------------------------------------------------------------*/
1218 /* getDataSize - get the operand data size */
1219 /*-----------------------------------------------------------------*/
1221 getDataSize (operand * op)
1224 size = AOP_SIZE (op);
1225 if (size == GPTRSIZE)
1227 sym_link *type = operandType (op);
1228 if (IS_GENPTR (type))
1230 /* generic pointer; arithmetic operations
1231 * should ignore the high byte (pointer type).
1239 /*-----------------------------------------------------------------*/
1240 /* outAcc - output Acc */
1241 /*-----------------------------------------------------------------*/
1243 outAcc (operand * result)
1246 size = getDataSize (result);
1249 aopPut (AOP (result), "a", 0);
1252 /* unsigned or positive */
1255 aopPut (AOP (result), zero, offset++);
1260 /*-----------------------------------------------------------------*/
1261 /* outBitC - output a bit C */
1262 /*-----------------------------------------------------------------*/
1264 outBitC (operand * result)
1266 /* if the result is bit */
1267 if (AOP_TYPE (result) == AOP_CRY)
1268 aopPut (AOP (result), "c", 0);
1271 emitcode ("clr", "a");
1272 emitcode ("rlc", "a");
1277 /*-----------------------------------------------------------------*/
1278 /* toBoolean - emit code for orl a,operator(sizeop) */
1279 /*-----------------------------------------------------------------*/
1281 toBoolean (operand * oper)
1283 int size = AOP_SIZE (oper) - 1;
1285 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1287 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1291 /*-----------------------------------------------------------------*/
1292 /* genNot - generate code for ! operation */
1293 /*-----------------------------------------------------------------*/
1298 sym_link *optype = operandType (IC_LEFT (ic));
1300 /* assign asmOps to operand & result */
1301 aopOp (IC_LEFT (ic), ic, FALSE);
1302 aopOp (IC_RESULT (ic), ic, TRUE);
1304 /* if in bit space then a special case */
1305 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1307 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1308 emitcode ("cpl", "c");
1309 outBitC (IC_RESULT (ic));
1313 /* if type float then do float */
1314 if (IS_FLOAT (optype))
1316 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1320 toBoolean (IC_LEFT (ic));
1322 tlbl = newiTempLabel (NULL);
1323 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1324 emitcode ("", "%05d$:", tlbl->key + 100);
1325 outBitC (IC_RESULT (ic));
1328 /* release the aops */
1329 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1334 /*-----------------------------------------------------------------*/
1335 /* genCpl - generate code for complement */
1336 /*-----------------------------------------------------------------*/
1344 /* assign asmOps to operand & result */
1345 aopOp (IC_LEFT (ic), ic, FALSE);
1346 aopOp (IC_RESULT (ic), ic, TRUE);
1348 /* if both are in bit space then
1350 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1351 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1354 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1355 emitcode ("cpl", "c");
1356 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1360 size = AOP_SIZE (IC_RESULT (ic));
1363 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1365 emitcode ("cpl", "a");
1366 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1371 /* release the aops */
1372 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1373 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1376 /*-----------------------------------------------------------------*/
1377 /* genUminusFloat - unary minus for floating points */
1378 /*-----------------------------------------------------------------*/
1380 genUminusFloat (operand * op, operand * result)
1382 int size, offset = 0;
1384 /* for this we just need to flip the
1385 first it then copy the rest in place */
1386 size = AOP_SIZE (op) - 1;
1387 l = aopGet (AOP (op), 3, FALSE, FALSE);
1391 emitcode ("cpl", "acc.7");
1392 aopPut (AOP (result), "a", 3);
1396 aopPut (AOP (result),
1397 aopGet (AOP (op), offset, FALSE, FALSE),
1403 /*-----------------------------------------------------------------*/
1404 /* genUminus - unary minus code generation */
1405 /*-----------------------------------------------------------------*/
1407 genUminus (iCode * ic)
1410 sym_link *optype, *rtype;
1414 aopOp (IC_LEFT (ic), ic, FALSE);
1415 aopOp (IC_RESULT (ic), ic, TRUE);
1417 /* if both in bit space then special
1419 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1420 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1423 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1424 emitcode ("cpl", "c");
1425 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1429 optype = operandType (IC_LEFT (ic));
1430 rtype = operandType (IC_RESULT (ic));
1432 /* if float then do float stuff */
1433 if (IS_FLOAT (optype))
1435 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1439 /* otherwise subtract from zero */
1440 size = AOP_SIZE (IC_LEFT (ic));
1445 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1446 if (!strcmp (l, "a"))
1450 emitcode ("cpl", "a");
1451 emitcode ("addc", "a,#0");
1457 emitcode ("clr", "a");
1458 emitcode ("subb", "a,%s", l);
1460 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1463 /* if any remaining bytes in the result */
1464 /* we just need to propagate the sign */
1465 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1467 emitcode ("rlc", "a");
1468 emitcode ("subb", "a,acc");
1470 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1474 /* release the aops */
1475 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1479 /*-----------------------------------------------------------------*/
1480 /* saveRegisters - will look for a call and save the registers */
1481 /*-----------------------------------------------------------------*/
1483 saveRegisters (iCode * lic)
1491 for (ic = lic; ic; ic = ic->next)
1492 if (ic->op == CALL || ic->op == PCALL)
1497 fprintf (stderr, "found parameter push with no function call\n");
1501 /* if the registers have been saved already then
1503 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1506 /* find the registers in use at this time
1507 and push them away to safety */
1508 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1512 if (options.useXstack)
1514 if (bitVectBitValue (rsave, R0_IDX))
1515 emitcode ("mov", "b,r0");
1516 emitcode ("mov", "r0,%s", spname);
1517 for (i = 0; i < mcs51_nRegs; i++)
1519 if (bitVectBitValue (rsave, i))
1522 emitcode ("mov", "a,b");
1524 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1525 emitcode ("movx", "@r0,a");
1526 emitcode ("inc", "r0");
1529 emitcode ("mov", "%s,r0", spname);
1530 if (bitVectBitValue (rsave, R0_IDX))
1531 emitcode ("mov", "r0,b");
1534 for (i = 0; i < mcs51_nRegs; i++)
1536 if (bitVectBitValue (rsave, i))
1537 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1540 detype = getSpec (operandType (IC_LEFT (ic)));
1542 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1543 IS_ISR (currFunc->etype) &&
1546 saverbank (SPEC_BANK (detype), ic, TRUE);
1549 /*-----------------------------------------------------------------*/
1550 /* unsaveRegisters - pop the pushed registers */
1551 /*-----------------------------------------------------------------*/
1553 unsaveRegisters (iCode * ic)
1557 /* find the registers in use at this time
1558 and push them away to safety */
1559 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1562 if (options.useXstack)
1564 emitcode ("mov", "r0,%s", spname);
1565 for (i = mcs51_nRegs; i >= 0; i--)
1567 if (bitVectBitValue (rsave, i))
1569 emitcode ("dec", "r0");
1570 emitcode ("movx", "a,@r0");
1572 emitcode ("mov", "b,a");
1574 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1578 emitcode ("mov", "%s,r0", spname);
1579 if (bitVectBitValue (rsave, R0_IDX))
1580 emitcode ("mov", "r0,b");
1583 for (i = mcs51_nRegs; i >= 0; i--)
1585 if (bitVectBitValue (rsave, i))
1586 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1592 /*-----------------------------------------------------------------*/
1594 /*-----------------------------------------------------------------*/
1596 pushSide (operand * oper, int size)
1601 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1602 if (AOP_TYPE (oper) != AOP_REG &&
1603 AOP_TYPE (oper) != AOP_DIR &&
1606 emitcode ("mov", "a,%s", l);
1607 emitcode ("push", "acc");
1610 emitcode ("push", "%s", l);
1614 /*-----------------------------------------------------------------*/
1615 /* assignResultValue - */
1616 /*-----------------------------------------------------------------*/
1618 assignResultValue (operand * oper)
1621 int size = AOP_SIZE (oper);
1624 aopPut (AOP (oper), fReturn[offset], offset);
1630 /*-----------------------------------------------------------------*/
1631 /* genXpush - pushes onto the external stack */
1632 /*-----------------------------------------------------------------*/
1634 genXpush (iCode * ic)
1636 asmop *aop = newAsmop (0);
1638 int size, offset = 0;
1640 aopOp (IC_LEFT (ic), ic, FALSE);
1641 r = getFreePtr (ic, &aop, FALSE);
1644 emitcode ("mov", "%s,_spx", r->name);
1646 size = AOP_SIZE (IC_LEFT (ic));
1650 char *l = aopGet (AOP (IC_LEFT (ic)),
1651 offset++, FALSE, FALSE);
1653 emitcode ("movx", "@%s,a", r->name);
1654 emitcode ("inc", "%s", r->name);
1659 emitcode ("mov", "_spx,%s", r->name);
1661 freeAsmop (NULL, aop, ic, TRUE);
1662 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1665 /*-----------------------------------------------------------------*/
1666 /* genIpush - genrate code for pushing this gets a little complex */
1667 /*-----------------------------------------------------------------*/
1669 genIpush (iCode * ic)
1671 int size, offset = 0;
1675 /* if this is not a parm push : ie. it is spill push
1676 and spill push is always done on the local stack */
1680 /* and the item is spilt then do nothing */
1681 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1684 aopOp (IC_LEFT (ic), ic, FALSE);
1685 size = AOP_SIZE (IC_LEFT (ic));
1686 /* push it on the stack */
1689 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1695 emitcode ("push", "%s", l);
1700 /* this is a paramter push: in this case we call
1701 the routine to find the call and save those
1702 registers that need to be saved */
1705 /* if use external stack then call the external
1706 stack pushing routine */
1707 if (options.useXstack)
1713 /* then do the push */
1714 aopOp (IC_LEFT (ic), ic, FALSE);
1717 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1718 size = AOP_SIZE (IC_LEFT (ic));
1722 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1723 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1724 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1727 emitcode ("mov", "a,%s", l);
1728 emitcode ("push", "acc");
1731 emitcode ("push", "%s", l);
1734 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* genIpop - recover the registers: can happen only for spilling */
1739 /*-----------------------------------------------------------------*/
1741 genIpop (iCode * ic)
1746 /* if the temp was not pushed then */
1747 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1750 aopOp (IC_LEFT (ic), ic, FALSE);
1751 size = AOP_SIZE (IC_LEFT (ic));
1752 offset = (size - 1);
1754 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1757 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1760 /*-----------------------------------------------------------------*/
1761 /* unsaverbank - restores the resgister bank from stack */
1762 /*-----------------------------------------------------------------*/
1764 unsaverbank (int bank, iCode * ic, bool popPsw)
1772 if (options.useXstack)
1775 r = getFreePtr (ic, &aop, FALSE);
1778 emitcode ("mov", "%s,_spx", r->name);
1779 emitcode ("movx", "a,@%s", r->name);
1780 emitcode ("mov", "psw,a");
1781 emitcode ("dec", "%s", r->name);
1785 emitcode ("pop", "psw");
1788 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1790 if (options.useXstack)
1792 emitcode ("movx", "a,@%s", r->name);
1793 emitcode ("mov", "(%s+%d),a",
1794 regs8051[i].base, 8 * bank + regs8051[i].offset);
1795 emitcode ("dec", "%s", r->name);
1799 emitcode ("pop", "(%s+%d)",
1800 regs8051[i].base, 8 * bank + regs8051[i].offset);
1803 if (options.useXstack)
1806 emitcode ("mov", "_spx,%s", r->name);
1807 freeAsmop (NULL, aop, ic, TRUE);
1812 /*-----------------------------------------------------------------*/
1813 /* saverbank - saves an entire register bank on the stack */
1814 /*-----------------------------------------------------------------*/
1816 saverbank (int bank, iCode * ic, bool pushPsw)
1822 if (options.useXstack)
1826 r = getFreePtr (ic, &aop, FALSE);
1827 emitcode ("mov", "%s,_spx", r->name);
1831 for (i = 0; i < mcs51_nRegs; i++)
1833 if (options.useXstack)
1835 emitcode ("inc", "%s", r->name);
1836 emitcode ("mov", "a,(%s+%d)",
1837 regs8051[i].base, 8 * bank + regs8051[i].offset);
1838 emitcode ("movx", "@%s,a", r->name);
1841 emitcode ("push", "(%s+%d)",
1842 regs8051[i].base, 8 * bank + regs8051[i].offset);
1847 if (options.useXstack)
1849 emitcode ("mov", "a,psw");
1850 emitcode ("movx", "@%s,a", r->name);
1851 emitcode ("inc", "%s", r->name);
1852 emitcode ("mov", "_spx,%s", r->name);
1853 freeAsmop (NULL, aop, ic, TRUE);
1857 emitcode ("push", "psw");
1859 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1865 /*-----------------------------------------------------------------*/
1866 /* genCall - generates a call statement */
1867 /*-----------------------------------------------------------------*/
1869 genCall (iCode * ic)
1873 /* if caller saves & we have not saved then */
1877 /* if we are calling a function that is not using
1878 the same register bank then we need to save the
1879 destination registers on the stack */
1880 detype = getSpec (operandType (IC_LEFT (ic)));
1882 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1883 IS_ISR (currFunc->etype) &&
1886 saverbank (SPEC_BANK (detype), ic, TRUE);
1888 /* if send set is not empty the assign */
1893 for (sic = setFirstItem (_G.sendSet); sic;
1894 sic = setNextItem (_G.sendSet))
1896 int size, offset = 0;
1897 aopOp (IC_LEFT (sic), sic, FALSE);
1898 size = AOP_SIZE (IC_LEFT (sic));
1901 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1903 if (strcmp (l, fReturn[offset]))
1904 emitcode ("mov", "%s,%s",
1909 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1914 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1915 OP_SYMBOL (IC_LEFT (ic))->rname :
1916 OP_SYMBOL (IC_LEFT (ic))->name));
1918 /* if we need assign a result value */
1919 if ((IS_ITEMP (IC_RESULT (ic)) &&
1920 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1921 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1922 IS_TRUE_SYMOP (IC_RESULT (ic)))
1926 aopOp (IC_RESULT (ic), ic, FALSE);
1929 assignResultValue (IC_RESULT (ic));
1931 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1934 /* adjust the stack for parameters if
1939 if (ic->parmBytes > 3)
1941 emitcode ("mov", "a,%s", spname);
1942 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1943 emitcode ("mov", "%s,a", spname);
1946 for (i = 0; i < ic->parmBytes; i++)
1947 emitcode ("dec", "%s", spname);
1951 /* if register bank was saved then pop them */
1953 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1955 /* if we hade saved some registers then unsave them */
1956 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1957 unsaveRegisters (ic);
1962 /*-----------------------------------------------------------------*/
1963 /* genPcall - generates a call by pointer statement */
1964 /*-----------------------------------------------------------------*/
1966 genPcall (iCode * ic)
1969 symbol *rlbl = newiTempLabel (NULL);
1972 /* if caller saves & we have not saved then */
1976 /* if we are calling a function that is not using
1977 the same register bank then we need to save the
1978 destination registers on the stack */
1979 detype = getSpec (operandType (IC_LEFT (ic)));
1981 IS_ISR (currFunc->etype) &&
1982 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1983 saverbank (SPEC_BANK (detype), ic, TRUE);
1986 /* push the return address on to the stack */
1987 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1988 emitcode ("push", "acc");
1989 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1990 emitcode ("push", "acc");
1992 /* now push the calling address */
1993 aopOp (IC_LEFT (ic), ic, FALSE);
1995 pushSide (IC_LEFT (ic), FPTRSIZE);
1997 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1999 /* if send set is not empty the assign */
2004 for (sic = setFirstItem (_G.sendSet); sic;
2005 sic = setNextItem (_G.sendSet))
2007 int size, offset = 0;
2008 aopOp (IC_LEFT (sic), sic, FALSE);
2009 size = AOP_SIZE (IC_LEFT (sic));
2012 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2014 if (strcmp (l, fReturn[offset]))
2015 emitcode ("mov", "%s,%s",
2020 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2025 emitcode ("ret", "");
2026 emitcode ("", "%05d$:", (rlbl->key + 100));
2029 /* if we need assign a result value */
2030 if ((IS_ITEMP (IC_RESULT (ic)) &&
2031 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2032 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2033 IS_TRUE_SYMOP (IC_RESULT (ic)))
2037 aopOp (IC_RESULT (ic), ic, FALSE);
2040 assignResultValue (IC_RESULT (ic));
2042 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2045 /* adjust the stack for parameters if
2050 if (ic->parmBytes > 3)
2052 emitcode ("mov", "a,%s", spname);
2053 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2054 emitcode ("mov", "%s,a", spname);
2057 for (i = 0; i < ic->parmBytes; i++)
2058 emitcode ("dec", "%s", spname);
2062 /* if register bank was saved then unsave them */
2064 (SPEC_BANK (currFunc->etype) !=
2065 SPEC_BANK (detype)))
2066 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2068 /* if we hade saved some registers then
2071 unsaveRegisters (ic);
2075 /*-----------------------------------------------------------------*/
2076 /* resultRemat - result is rematerializable */
2077 /*-----------------------------------------------------------------*/
2079 resultRemat (iCode * ic)
2081 if (SKIP_IC (ic) || ic->op == IFX)
2084 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2086 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2087 if (sym->remat && !POINTER_SET (ic))
2094 #if defined(__BORLANDC__) || defined(_MSC_VER)
2095 #define STRCASECMP stricmp
2097 #define STRCASECMP strcasecmp
2100 /*-----------------------------------------------------------------*/
2101 /* inExcludeList - return 1 if the string is in exclude Reg list */
2102 /*-----------------------------------------------------------------*/
2104 inExcludeList (char *s)
2108 if (options.excludeRegs[i] &&
2109 STRCASECMP (options.excludeRegs[i], "none") == 0)
2112 for (i = 0; options.excludeRegs[i]; i++)
2114 if (options.excludeRegs[i] &&
2115 STRCASECMP (s, options.excludeRegs[i]) == 0)
2121 /*-----------------------------------------------------------------*/
2122 /* genFunction - generated code for function entry */
2123 /*-----------------------------------------------------------------*/
2125 genFunction (iCode * ic)
2131 /* create the function header */
2132 emitcode (";", "-----------------------------------------");
2133 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2134 emitcode (";", "-----------------------------------------");
2136 emitcode ("", "%s:", sym->rname);
2137 fetype = getSpec (operandType (IC_LEFT (ic)));
2139 /* if critical function then turn interrupts off */
2140 if (SPEC_CRTCL (fetype))
2141 emitcode ("clr", "ea");
2143 /* here we need to generate the equates for the
2144 register bank if required */
2145 if (SPEC_BANK (fetype) != rbank)
2149 rbank = SPEC_BANK (fetype);
2150 for (i = 0; i < mcs51_nRegs; i++)
2152 if (strcmp (regs8051[i].base, "0") == 0)
2153 emitcode ("", "%s = 0x%02x",
2155 8 * rbank + regs8051[i].offset);
2157 emitcode ("", "%s = %s + 0x%02x",
2160 8 * rbank + regs8051[i].offset);
2164 /* if this is an interrupt service routine then
2165 save acc, b, dpl, dph */
2166 if (IS_ISR (sym->etype))
2169 if (!inExcludeList ("acc"))
2170 emitcode ("push", "acc");
2171 if (!inExcludeList ("b"))
2172 emitcode ("push", "b");
2173 if (!inExcludeList ("dpl"))
2174 emitcode ("push", "dpl");
2175 if (!inExcludeList ("dph"))
2176 emitcode ("push", "dph");
2177 /* if this isr has no bank i.e. is going to
2178 run with bank 0 , then we need to save more
2180 if (!SPEC_BANK (sym->etype))
2183 /* if this function does not call any other
2184 function then we can be economical and
2185 save only those registers that are used */
2190 /* if any registers used */
2193 /* save the registers used */
2194 for (i = 0; i < sym->regsUsed->size; i++)
2196 if (bitVectBitValue (sym->regsUsed, i) ||
2197 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2198 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2205 /* this function has a function call cannot
2206 determines register usage so we will have the
2208 saverbank (0, ic, FALSE);
2214 /* if callee-save to be used for this function
2215 then save the registers being used in this function */
2216 if (sym->calleeSave)
2220 /* if any registers used */
2223 /* save the registers used */
2224 for (i = 0; i < sym->regsUsed->size; i++)
2226 if (bitVectBitValue (sym->regsUsed, i) ||
2227 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2229 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2237 /* set the register bank to the desired value */
2238 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2240 emitcode ("push", "psw");
2241 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2244 if (IS_RENT (sym->etype) || options.stackAuto)
2247 if (options.useXstack)
2249 emitcode ("mov", "r0,%s", spname);
2250 emitcode ("mov", "a,_bp");
2251 emitcode ("movx", "@r0,a");
2252 emitcode ("inc", "%s", spname);
2256 /* set up the stack */
2257 emitcode ("push", "_bp"); /* save the callers stack */
2259 emitcode ("mov", "_bp,%s", spname);
2262 /* adjust the stack for the function */
2268 werror (W_STACK_OVERFLOW, sym->name);
2270 if (i > 3 && sym->recvSize < 4)
2273 emitcode ("mov", "a,sp");
2274 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2275 emitcode ("mov", "sp,a");
2280 emitcode ("inc", "sp");
2286 emitcode ("mov", "a,_spx");
2287 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2288 emitcode ("mov", "_spx,a");
2293 /*-----------------------------------------------------------------*/
2294 /* genEndFunction - generates epilogue for functions */
2295 /*-----------------------------------------------------------------*/
2297 genEndFunction (iCode * ic)
2299 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2301 if (IS_RENT (sym->etype) || options.stackAuto)
2303 emitcode ("mov", "%s,_bp", spname);
2306 /* if use external stack but some variables were
2307 added to the local stack then decrement the
2309 if (options.useXstack && sym->stack)
2311 emitcode ("mov", "a,sp");
2312 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2313 emitcode ("mov", "sp,a");
2317 if ((IS_RENT (sym->etype) || options.stackAuto))
2319 if (options.useXstack)
2321 emitcode ("mov", "r0,%s", spname);
2322 emitcode ("movx", "a,@r0");
2323 emitcode ("mov", "_bp,a");
2324 emitcode ("dec", "%s", spname);
2328 emitcode ("pop", "_bp");
2332 /* restore the register bank */
2333 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2334 emitcode ("pop", "psw");
2336 if (IS_ISR (sym->etype))
2339 /* now we need to restore the registers */
2340 /* if this isr has no bank i.e. is going to
2341 run with bank 0 , then we need to save more
2343 if (!SPEC_BANK (sym->etype))
2346 /* if this function does not call any other
2347 function then we can be economical and
2348 save only those registers that are used */
2353 /* if any registers used */
2356 /* save the registers used */
2357 for (i = sym->regsUsed->size; i >= 0; i--)
2359 if (bitVectBitValue (sym->regsUsed, i) ||
2360 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2361 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2368 /* this function has a function call cannot
2369 determines register usage so we will have the
2371 unsaverbank (0, ic, FALSE);
2375 if (!inExcludeList ("dph"))
2376 emitcode ("pop", "dph");
2377 if (!inExcludeList ("dpl"))
2378 emitcode ("pop", "dpl");
2379 if (!inExcludeList ("b"))
2380 emitcode ("pop", "b");
2381 if (!inExcludeList ("acc"))
2382 emitcode ("pop", "acc");
2384 if (SPEC_CRTCL (sym->etype))
2385 emitcode ("setb", "ea");
2387 /* if debug then send end of function */
2388 /* if (options.debug && currFunc) { */
2392 emitcode ("", "C$%s$%d$%d$%d ==.",
2393 FileBaseName (ic->filename), currFunc->lastLine,
2394 ic->level, ic->block);
2395 if (IS_STATIC (currFunc->etype))
2396 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2398 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2402 emitcode ("reti", "");
2406 if (SPEC_CRTCL (sym->etype))
2407 emitcode ("setb", "ea");
2409 if (sym->calleeSave)
2413 /* if any registers used */
2416 /* save the registers used */
2417 for (i = sym->regsUsed->size; i >= 0; i--)
2419 if (bitVectBitValue (sym->regsUsed, i) ||
2420 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2421 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2427 /* if debug then send end of function */
2431 emitcode ("", "C$%s$%d$%d$%d ==.",
2432 FileBaseName (ic->filename), currFunc->lastLine,
2433 ic->level, ic->block);
2434 if (IS_STATIC (currFunc->etype))
2435 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2437 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2441 emitcode ("ret", "");
2446 /*-----------------------------------------------------------------*/
2447 /* genRet - generate code for return statement */
2448 /*-----------------------------------------------------------------*/
2452 int size, offset = 0, pushed = 0;
2454 /* if we have no return value then
2455 just generate the "ret" */
2459 /* we have something to return then
2460 move the return value into place */
2461 aopOp (IC_LEFT (ic), ic, FALSE);
2462 size = AOP_SIZE (IC_LEFT (ic));
2467 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2470 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2472 emitcode ("push", "%s", l);
2477 l = aopGet (AOP (IC_LEFT (ic)), offset,
2479 if (strcmp (fReturn[offset], l))
2480 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2489 if (strcmp (fReturn[pushed], "a"))
2490 emitcode ("pop", fReturn[pushed]);
2492 emitcode ("pop", "acc");
2495 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2498 /* generate a jump to the return label
2499 if the next is not the return statement */
2500 if (!(ic->next && ic->next->op == LABEL &&
2501 IC_LABEL (ic->next) == returnLabel))
2503 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2507 /*-----------------------------------------------------------------*/
2508 /* genLabel - generates a label */
2509 /*-----------------------------------------------------------------*/
2511 genLabel (iCode * ic)
2513 /* special case never generate */
2514 if (IC_LABEL (ic) == entryLabel)
2517 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2520 /*-----------------------------------------------------------------*/
2521 /* genGoto - generates a ljmp */
2522 /*-----------------------------------------------------------------*/
2524 genGoto (iCode * ic)
2526 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2529 /*-----------------------------------------------------------------*/
2530 /* findLabelBackwards: walks back through the iCode chain looking */
2531 /* for the given label. Returns number of iCode instructions */
2532 /* between that label and given ic. */
2533 /* Returns zero if label not found. */
2534 /*-----------------------------------------------------------------*/
2536 findLabelBackwards (iCode * ic, int key)
2545 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2547 /* printf("findLabelBackwards = %d\n", count); */
2555 /*-----------------------------------------------------------------*/
2556 /* genPlusIncr :- does addition with increment if possible */
2557 /*-----------------------------------------------------------------*/
2559 genPlusIncr (iCode * ic)
2561 unsigned int icount;
2562 unsigned int size = getDataSize (IC_RESULT (ic));
2564 /* will try to generate an increment */
2565 /* if the right side is not a literal
2567 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2570 /* if the literal value of the right hand side
2571 is greater than 4 then it is not worth it */
2572 if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2575 /* if increment 16 bits in register */
2576 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2584 /* If the next instruction is a goto and the goto target
2585 * is < 10 instructions previous to this, we can generate
2586 * jumps straight to that target.
2588 if (ic->next && ic->next->op == GOTO
2589 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2590 && labelRange <= 10)
2592 emitcode (";", "tail increment optimized");
2593 tlbl = IC_LABEL (ic->next);
2598 tlbl = newiTempLabel (NULL);
2601 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2602 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2603 IS_AOP_PREG (IC_RESULT (ic)))
2604 emitcode ("cjne", "%s,#0x00,%05d$"
2605 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2609 emitcode ("clr", "a");
2610 emitcode ("cjne", "a,%s,%05d$"
2611 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2615 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2618 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2619 IS_AOP_PREG (IC_RESULT (ic)))
2620 emitcode ("cjne", "%s,#0x00,%05d$"
2621 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2624 emitcode ("cjne", "a,%s,%05d$"
2625 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2628 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2632 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2633 IS_AOP_PREG (IC_RESULT (ic)))
2634 emitcode ("cjne", "%s,#0x00,%05d$"
2635 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2639 emitcode ("cjne", "a,%s,%05d$"
2640 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2643 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2648 emitcode ("", "%05d$:", tlbl->key + 100);
2653 /* if the sizes are greater than 1 then we cannot */
2654 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2655 AOP_SIZE (IC_LEFT (ic)) > 1)
2658 /* we can if the aops of the left & result match or
2659 if they are in registers and the registers are the
2661 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2666 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2667 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2668 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2674 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2683 /*-----------------------------------------------------------------*/
2684 /* outBitAcc - output a bit in acc */
2685 /*-----------------------------------------------------------------*/
2687 outBitAcc (operand * result)
2689 symbol *tlbl = newiTempLabel (NULL);
2690 /* if the result is a bit */
2691 if (AOP_TYPE (result) == AOP_CRY)
2693 aopPut (AOP (result), "a", 0);
2697 emitcode ("jz", "%05d$", tlbl->key + 100);
2698 emitcode ("mov", "a,%s", one);
2699 emitcode ("", "%05d$:", tlbl->key + 100);
2704 /*-----------------------------------------------------------------*/
2705 /* genPlusBits - generates code for addition of two bits */
2706 /*-----------------------------------------------------------------*/
2708 genPlusBits (iCode * ic)
2710 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2712 symbol *lbl = newiTempLabel (NULL);
2713 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2714 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2715 emitcode ("cpl", "c");
2716 emitcode ("", "%05d$:", (lbl->key + 100));
2717 outBitC (IC_RESULT (ic));
2721 emitcode ("clr", "a");
2722 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2723 emitcode ("rlc", "a");
2724 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2725 emitcode ("addc", "a,#0x00");
2726 outAcc (IC_RESULT (ic));
2731 /* This is the original version of this code.
2733 * This is being kept around for reference,
2734 * because I am not entirely sure I got it right...
2737 adjustArithmeticResult (iCode * ic)
2739 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2740 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2741 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2742 aopPut (AOP (IC_RESULT (ic)),
2743 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2746 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2747 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2748 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2749 aopPut (AOP (IC_RESULT (ic)),
2750 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2753 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2754 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2755 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2756 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2757 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2760 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2761 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2765 /* This is the pure and virtuous version of this code.
2766 * I'm pretty certain it's right, but not enough to toss the old
2770 adjustArithmeticResult (iCode * ic)
2772 if (opIsGptr (IC_RESULT (ic)) &&
2773 opIsGptr (IC_LEFT (ic)) &&
2774 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2776 aopPut (AOP (IC_RESULT (ic)),
2777 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2781 if (opIsGptr (IC_RESULT (ic)) &&
2782 opIsGptr (IC_RIGHT (ic)) &&
2783 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2785 aopPut (AOP (IC_RESULT (ic)),
2786 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2790 if (opIsGptr (IC_RESULT (ic)) &&
2791 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2792 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2793 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2794 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2797 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2798 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2803 /*-----------------------------------------------------------------*/
2804 /* genPlus - generates code for addition */
2805 /*-----------------------------------------------------------------*/
2807 genPlus (iCode * ic)
2809 int size, offset = 0;
2811 /* special cases :- */
2813 aopOp (IC_LEFT (ic), ic, FALSE);
2814 aopOp (IC_RIGHT (ic), ic, FALSE);
2815 aopOp (IC_RESULT (ic), ic, TRUE);
2817 /* if literal, literal on the right or
2818 if left requires ACC or right is already
2820 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2821 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2822 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2824 operand *t = IC_RIGHT (ic);
2825 IC_RIGHT (ic) = IC_LEFT (ic);
2829 /* if both left & right are in bit
2831 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2832 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2838 /* if left in bit space & right literal */
2839 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2840 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2842 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2843 /* if result in bit space */
2844 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2846 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2847 emitcode ("cpl", "c");
2848 outBitC (IC_RESULT (ic));
2852 size = getDataSize (IC_RESULT (ic));
2855 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2856 emitcode ("addc", "a,#00");
2857 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2863 /* if I can do an increment instead
2864 of add then GOOD for ME */
2865 if (genPlusIncr (ic) == TRUE)
2868 size = getDataSize (IC_RESULT (ic));
2872 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2874 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2876 emitcode ("add", "a,%s",
2877 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2879 emitcode ("addc", "a,%s",
2880 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2884 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2886 emitcode ("add", "a,%s",
2887 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2889 emitcode ("addc", "a,%s",
2890 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2892 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2895 adjustArithmeticResult (ic);
2898 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2899 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2900 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2903 /*-----------------------------------------------------------------*/
2904 /* genMinusDec :- does subtraction with deccrement if possible */
2905 /*-----------------------------------------------------------------*/
2907 genMinusDec (iCode * ic)
2909 unsigned int icount;
2910 unsigned int size = getDataSize (IC_RESULT (ic));
2912 /* will try to generate an increment */
2913 /* if the right side is not a literal
2915 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2918 /* if the literal value of the right hand side
2919 is greater than 4 then it is not worth it */
2920 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2923 /* if decrement 16 bits in register */
2924 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2932 /* If the next instruction is a goto and the goto target
2933 * is <= 10 instructions previous to this, we can generate
2934 * jumps straight to that target.
2936 if (ic->next && ic->next->op == GOTO
2937 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2938 && labelRange <= 10)
2940 emitcode (";", "tail decrement optimized");
2941 tlbl = IC_LABEL (ic->next);
2946 tlbl = newiTempLabel (NULL);
2950 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2951 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2952 IS_AOP_PREG (IC_RESULT (ic)))
2953 emitcode ("cjne", "%s,#0xff,%05d$"
2954 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2958 emitcode ("mov", "a,#0xff");
2959 emitcode ("cjne", "a,%s,%05d$"
2960 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2963 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2966 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2967 IS_AOP_PREG (IC_RESULT (ic)))
2968 emitcode ("cjne", "%s,#0xff,%05d$"
2969 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2973 emitcode ("cjne", "a,%s,%05d$"
2974 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2977 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0xff,%05d$"
2984 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2988 emitcode ("cjne", "a,%s,%05d$"
2989 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2992 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2996 emitcode ("", "%05d$:", tlbl->key + 100);
3001 /* if the sizes are greater than 1 then we cannot */
3002 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3003 AOP_SIZE (IC_LEFT (ic)) > 1)
3006 /* we can if the aops of the left & result match or
3007 if they are in registers and the registers are the
3009 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3013 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3021 /*-----------------------------------------------------------------*/
3022 /* addSign - complete with sign */
3023 /*-----------------------------------------------------------------*/
3025 addSign (operand * result, int offset, int sign)
3027 int size = (getDataSize (result) - offset);
3032 emitcode ("rlc", "a");
3033 emitcode ("subb", "a,acc");
3035 aopPut (AOP (result), "a", offset++);
3039 aopPut (AOP (result), zero, offset++);
3043 /*-----------------------------------------------------------------*/
3044 /* genMinusBits - generates code for subtraction of two bits */
3045 /*-----------------------------------------------------------------*/
3047 genMinusBits (iCode * ic)
3049 symbol *lbl = newiTempLabel (NULL);
3050 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3052 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3053 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3054 emitcode ("cpl", "c");
3055 emitcode ("", "%05d$:", (lbl->key + 100));
3056 outBitC (IC_RESULT (ic));
3060 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3061 emitcode ("subb", "a,acc");
3062 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3063 emitcode ("inc", "a");
3064 emitcode ("", "%05d$:", (lbl->key + 100));
3065 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3066 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3070 /*-----------------------------------------------------------------*/
3071 /* genMinus - generates code for subtraction */
3072 /*-----------------------------------------------------------------*/
3074 genMinus (iCode * ic)
3076 int size, offset = 0;
3077 unsigned long lit = 0L;
3079 aopOp (IC_LEFT (ic), ic, FALSE);
3080 aopOp (IC_RIGHT (ic), ic, FALSE);
3081 aopOp (IC_RESULT (ic), ic, TRUE);
3083 /* special cases :- */
3084 /* if both left & right are in bit space */
3085 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3086 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3092 /* if I can do an decrement instead
3093 of subtract then GOOD for ME */
3094 if (genMinusDec (ic) == TRUE)
3097 size = getDataSize (IC_RESULT (ic));
3099 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3105 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3109 /* if literal, add a,#-lit, else normal subb */
3112 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3113 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3114 emitcode ("subb", "a,%s",
3115 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3118 /* first add without previous c */
3120 emitcode ("add", "a,#0x%02x",
3121 (unsigned int) (lit & 0x0FFL));
3123 emitcode ("addc", "a,#0x%02x",
3124 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3126 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3129 adjustArithmeticResult (ic);
3132 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3133 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3134 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3138 /*-----------------------------------------------------------------*/
3139 /* genMultbits :- multiplication of bits */
3140 /*-----------------------------------------------------------------*/
3142 genMultbits (operand * left,
3146 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3147 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3152 /*-----------------------------------------------------------------*/
3153 /* genMultOneByte : 8*8=8/16 bit multiplication */
3154 /*-----------------------------------------------------------------*/
3157 genMultOneByte (operand * left,
3161 sym_link *opetype = operandType (result);
3166 /* (if two literals, the value is computed before) */
3167 /* if one literal, literal on the right */
3168 if (AOP_TYPE (left) == AOP_LIT)
3175 size = AOP_SIZE (result);
3176 /* signed or unsigned */
3177 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3178 l = aopGet (AOP (left), 0, FALSE, FALSE);
3180 emitcode ("mul", "ab");
3181 /* if result size = 1, mul signed = mul unsigned */
3182 aopPut (AOP (result), "a", 0);
3185 if (SPEC_USIGN (opetype))
3187 aopPut (AOP (result), "b", 1);
3189 /* for filling the MSBs */
3190 emitcode ("clr", "a");
3194 emitcode ("mov", "a,b");
3196 /* adjust the MSB if left or right neg */
3198 /* if one literal */
3199 if (AOP_TYPE (right) == AOP_LIT)
3201 /* AND literal negative */
3202 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3204 /* adjust MSB (c==0 after mul) */
3205 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3210 lbl = newiTempLabel (NULL);
3211 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3212 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3213 emitcode ("", "%05d$:", (lbl->key + 100));
3214 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3215 lbl = newiTempLabel (NULL);
3216 emitcode ("jc", "%05d$", (lbl->key + 100));
3217 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3218 emitcode ("", "%05d$:", (lbl->key + 100));
3221 lbl = newiTempLabel (NULL);
3222 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3223 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3224 emitcode ("", "%05d$:", (lbl->key + 100));
3225 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3226 lbl = newiTempLabel (NULL);
3227 emitcode ("jc", "%05d$", (lbl->key + 100));
3228 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3229 emitcode ("", "%05d$:", (lbl->key + 100));
3231 aopPut (AOP (result), "a", 1);
3235 emitcode ("rlc", "a");
3236 emitcode ("subb", "a,acc");
3243 aopPut (AOP (result), "a", offset++);
3248 genMultOneByte (operand * left,
3252 sym_link *opetype = operandType (result);
3254 int size=AOP_SIZE(result);
3256 //emitcode (";",__FUNCTION__);
3257 if (size<1 || size>2) {
3258 // this should never happen
3259 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3260 AOP_SIZE(result), __FUNCTION__, lineno);
3264 /* (if two literals: the value is computed before) */
3265 /* if one literal, literal on the right */
3266 if (AOP_TYPE (left) == AOP_LIT)
3271 //emitcode (";", "swapped left and right");
3274 if (SPEC_USIGN(opetype)
3275 // ignore the sign of left and right, what else can we do?
3276 || (SPEC_USIGN(operandType(left)) &&
3277 SPEC_USIGN(operandType(right)))) {
3278 // just an unsigned 8*8=8/16 multiply
3279 //emitcode (";","unsigned");
3280 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3281 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3282 emitcode ("mul", "ab");
3283 aopPut (AOP (result), "a", 0);
3285 aopPut (AOP (result), "b", 1);
3290 // we have to do a signed multiply
3292 //emitcode (";", "signed");
3293 emitcode ("clr", "F0"); // reset sign flag
3294 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3295 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3297 lbl=newiTempLabel(NULL);
3298 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3299 // left side is negative, 8-bit two's complement, this fails for -128
3300 emitcode ("setb", "F0"); // set sign flag
3301 emitcode ("cpl", "a");
3302 emitcode ("inc", "a");
3304 emitcode ("", "%05d$:", lbl->key+100);
3305 emitcode ("xch", "a,b");
3308 if (AOP_TYPE(right)==AOP_LIT) {
3309 /* AND literal negative */
3310 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3311 // two's complement for literal<0
3312 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3313 emitcode ("cpl", "a");
3314 emitcode ("inc", "a");
3317 lbl=newiTempLabel(NULL);
3318 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3319 // right side is negative, 8-bit two's complement
3320 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3321 emitcode ("cpl", "a");
3322 emitcode ("inc", "a");
3323 emitcode ("", "%05d$:", lbl->key+100);
3325 emitcode ("mul", "ab");
3327 lbl=newiTempLabel(NULL);
3328 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3329 // only ONE op was negative, we have to do a 8/16-bit two's complement
3330 emitcode ("cpl", "a"); // lsb
3332 emitcode ("inc", "a");
3334 emitcode ("add", "a,#1");
3335 emitcode ("xch", "a,b");
3336 emitcode ("cpl", "a"); // msb
3337 emitcode ("addc", "a,#0");
3338 emitcode ("xch", "a,b");
3341 emitcode ("", "%05d$:", lbl->key+100);
3342 aopPut (AOP (result), "a", 0);
3344 aopPut (AOP (result), "b", 1);
3349 /*-----------------------------------------------------------------*/
3350 /* genMult - generates code for multiplication */
3351 /*-----------------------------------------------------------------*/
3353 genMult (iCode * ic)
3355 operand *left = IC_LEFT (ic);
3356 operand *right = IC_RIGHT (ic);
3357 operand *result = IC_RESULT (ic);
3359 /* assign the amsops */
3360 aopOp (left, ic, FALSE);
3361 aopOp (right, ic, FALSE);
3362 aopOp (result, ic, TRUE);
3364 /* special cases first */
3366 if (AOP_TYPE (left) == AOP_CRY &&
3367 AOP_TYPE (right) == AOP_CRY)
3369 genMultbits (left, right, result);
3373 /* if both are of size == 1 */
3374 if (AOP_SIZE (left) == 1 &&
3375 AOP_SIZE (right) == 1)
3377 genMultOneByte (left, right, result);
3381 /* should have been converted to function call */
3385 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3387 freeAsmop (result, NULL, ic, TRUE);
3390 /*-----------------------------------------------------------------*/
3391 /* genDivbits :- division of bits */
3392 /*-----------------------------------------------------------------*/
3394 genDivbits (operand * left,
3401 /* the result must be bit */
3402 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3403 l = aopGet (AOP (left), 0, FALSE, FALSE);
3407 emitcode ("div", "ab");
3408 emitcode ("rrc", "a");
3409 aopPut (AOP (result), "c", 0);
3412 /*-----------------------------------------------------------------*/
3413 /* genDivOneByte : 8 bit division */
3414 /*-----------------------------------------------------------------*/
3416 genDivOneByte (operand * left,
3420 sym_link *opetype = operandType (result);
3425 size = AOP_SIZE (result) - 1;
3427 /* signed or unsigned */
3428 if (SPEC_USIGN (opetype))
3430 /* unsigned is easy */
3431 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3432 l = aopGet (AOP (left), 0, FALSE, FALSE);
3434 emitcode ("div", "ab");
3435 aopPut (AOP (result), "a", 0);
3437 aopPut (AOP (result), zero, offset++);
3441 /* signed is a little bit more difficult */
3443 /* save the signs of the operands */
3444 l = aopGet (AOP (left), 0, FALSE, FALSE);
3446 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3447 emitcode ("push", "acc"); /* save it on the stack */
3449 /* now sign adjust for both left & right */
3450 l = aopGet (AOP (right), 0, FALSE, FALSE);
3452 lbl = newiTempLabel (NULL);
3453 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3454 emitcode ("cpl", "a");
3455 emitcode ("inc", "a");
3456 emitcode ("", "%05d$:", (lbl->key + 100));
3457 emitcode ("mov", "b,a");
3459 /* sign adjust left side */
3460 l = aopGet (AOP (left), 0, FALSE, FALSE);
3463 lbl = newiTempLabel (NULL);
3464 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3465 emitcode ("cpl", "a");
3466 emitcode ("inc", "a");
3467 emitcode ("", "%05d$:", (lbl->key + 100));
3469 /* now the division */
3470 emitcode ("div", "ab");
3471 /* we are interested in the lower order
3473 emitcode ("mov", "b,a");
3474 lbl = newiTempLabel (NULL);
3475 emitcode ("pop", "acc");
3476 /* if there was an over flow we don't
3477 adjust the sign of the result */
3478 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3479 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3481 emitcode ("clr", "a");
3482 emitcode ("subb", "a,b");
3483 emitcode ("mov", "b,a");
3484 emitcode ("", "%05d$:", (lbl->key + 100));
3486 /* now we are done */
3487 aopPut (AOP (result), "b", 0);
3490 emitcode ("mov", "c,b.7");
3491 emitcode ("subb", "a,acc");
3494 aopPut (AOP (result), "a", offset++);
3498 /*-----------------------------------------------------------------*/
3499 /* genDiv - generates code for division */
3500 /*-----------------------------------------------------------------*/
3504 operand *left = IC_LEFT (ic);
3505 operand *right = IC_RIGHT (ic);
3506 operand *result = IC_RESULT (ic);
3508 /* assign the amsops */
3509 aopOp (left, ic, FALSE);
3510 aopOp (right, ic, FALSE);
3511 aopOp (result, ic, TRUE);
3513 /* special cases first */
3515 if (AOP_TYPE (left) == AOP_CRY &&
3516 AOP_TYPE (right) == AOP_CRY)
3518 genDivbits (left, right, result);
3522 /* if both are of size == 1 */
3523 if (AOP_SIZE (left) == 1 &&
3524 AOP_SIZE (right) == 1)
3526 genDivOneByte (left, right, result);
3530 /* should have been converted to function call */
3533 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3535 freeAsmop (result, NULL, ic, TRUE);
3538 /*-----------------------------------------------------------------*/
3539 /* genModbits :- modulus of bits */
3540 /*-----------------------------------------------------------------*/
3542 genModbits (operand * left,
3549 /* the result must be bit */
3550 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3551 l = aopGet (AOP (left), 0, FALSE, FALSE);
3555 emitcode ("div", "ab");
3556 emitcode ("mov", "a,b");
3557 emitcode ("rrc", "a");
3558 aopPut (AOP (result), "c", 0);
3561 /*-----------------------------------------------------------------*/
3562 /* genModOneByte : 8 bit modulus */
3563 /*-----------------------------------------------------------------*/
3565 genModOneByte (operand * left,
3569 sym_link *opetype = operandType (result);
3573 /* signed or unsigned */
3574 if (SPEC_USIGN (opetype))
3576 /* unsigned is easy */
3577 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3578 l = aopGet (AOP (left), 0, FALSE, FALSE);
3580 emitcode ("div", "ab");
3581 aopPut (AOP (result), "b", 0);
3585 /* signed is a little bit more difficult */
3587 /* save the signs of the operands */
3588 l = aopGet (AOP (left), 0, FALSE, FALSE);
3591 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3592 emitcode ("push", "acc"); /* save it on the stack */
3594 /* now sign adjust for both left & right */
3595 l = aopGet (AOP (right), 0, FALSE, FALSE);
3598 lbl = newiTempLabel (NULL);
3599 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3600 emitcode ("cpl", "a");
3601 emitcode ("inc", "a");
3602 emitcode ("", "%05d$:", (lbl->key + 100));
3603 emitcode ("mov", "b,a");
3605 /* sign adjust left side */
3606 l = aopGet (AOP (left), 0, FALSE, FALSE);
3609 lbl = newiTempLabel (NULL);
3610 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3611 emitcode ("cpl", "a");
3612 emitcode ("inc", "a");
3613 emitcode ("", "%05d$:", (lbl->key + 100));
3615 /* now the multiplication */
3616 emitcode ("div", "ab");
3617 /* we are interested in the lower order
3619 lbl = newiTempLabel (NULL);
3620 emitcode ("pop", "acc");
3621 /* if there was an over flow we don't
3622 adjust the sign of the result */
3623 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3624 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3626 emitcode ("clr", "a");
3627 emitcode ("subb", "a,b");
3628 emitcode ("mov", "b,a");
3629 emitcode ("", "%05d$:", (lbl->key + 100));
3631 /* now we are done */
3632 aopPut (AOP (result), "b", 0);
3636 /*-----------------------------------------------------------------*/
3637 /* genMod - generates code for division */
3638 /*-----------------------------------------------------------------*/
3642 operand *left = IC_LEFT (ic);
3643 operand *right = IC_RIGHT (ic);
3644 operand *result = IC_RESULT (ic);
3646 /* assign the amsops */
3647 aopOp (left, ic, FALSE);
3648 aopOp (right, ic, FALSE);
3649 aopOp (result, ic, TRUE);
3651 /* special cases first */
3653 if (AOP_TYPE (left) == AOP_CRY &&
3654 AOP_TYPE (right) == AOP_CRY)
3656 genModbits (left, right, result);
3660 /* if both are of size == 1 */
3661 if (AOP_SIZE (left) == 1 &&
3662 AOP_SIZE (right) == 1)
3664 genModOneByte (left, right, result);
3668 /* should have been converted to function call */
3672 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3674 freeAsmop (result, NULL, ic, TRUE);
3677 /*-----------------------------------------------------------------*/
3678 /* genIfxJump :- will create a jump depending on the ifx */
3679 /*-----------------------------------------------------------------*/
3681 genIfxJump (iCode * ic, char *jval)
3684 symbol *tlbl = newiTempLabel (NULL);
3687 /* if true label then we jump if condition
3691 jlbl = IC_TRUE (ic);
3692 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3693 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3697 /* false label is present */
3698 jlbl = IC_FALSE (ic);
3699 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3700 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3702 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3703 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3705 emitcode (inst, "%05d$", tlbl->key + 100);
3706 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3707 emitcode ("", "%05d$:", tlbl->key + 100);
3709 /* mark the icode as generated */
3713 /*-----------------------------------------------------------------*/
3714 /* genCmp :- greater or less than comparison */
3715 /*-----------------------------------------------------------------*/
3717 genCmp (operand * left, operand * right,
3718 operand * result, iCode * ifx, int sign)
3720 int size, offset = 0;
3721 unsigned long lit = 0L;
3723 /* if left & right are bit variables */
3724 if (AOP_TYPE (left) == AOP_CRY &&
3725 AOP_TYPE (right) == AOP_CRY)
3727 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3728 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3732 /* subtract right from left if at the
3733 end the carry flag is set then we know that
3734 left is greater than right */
3735 size = max (AOP_SIZE (left), AOP_SIZE (right));
3737 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3738 if ((size == 1) && !sign &&
3739 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3741 symbol *lbl = newiTempLabel (NULL);
3742 emitcode ("cjne", "%s,%s,%05d$",
3743 aopGet (AOP (left), offset, FALSE, FALSE),
3744 aopGet (AOP (right), offset, FALSE, FALSE),
3746 emitcode ("", "%05d$:", lbl->key + 100);
3750 if (AOP_TYPE (right) == AOP_LIT)
3752 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3753 /* optimize if(x < 0) or if(x >= 0) */
3762 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3763 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3765 genIfxJump (ifx, "acc.7");
3769 emitcode ("rlc", "a");
3777 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3778 if (sign && size == 0)
3780 emitcode ("xrl", "a,#0x80");
3781 if (AOP_TYPE (right) == AOP_LIT)
3783 unsigned long lit = (unsigned long)
3784 floatFromVal (AOP (right)->aopu.aop_lit);
3785 emitcode ("subb", "a,#0x%02x",
3786 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3790 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3791 emitcode ("xrl", "b,#0x80");
3792 emitcode ("subb", "a,b");
3796 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3802 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3808 /* if the result is used in the next
3809 ifx conditional branch then generate
3810 code a little differently */
3812 genIfxJump (ifx, "c");
3815 /* leave the result in acc */
3819 /*-----------------------------------------------------------------*/
3820 /* genCmpGt :- greater than comparison */
3821 /*-----------------------------------------------------------------*/
3823 genCmpGt (iCode * ic, iCode * ifx)
3825 operand *left, *right, *result;
3826 sym_link *letype, *retype;
3829 left = IC_LEFT (ic);
3830 right = IC_RIGHT (ic);
3831 result = IC_RESULT (ic);
3833 letype = getSpec (operandType (left));
3834 retype = getSpec (operandType (right));
3835 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3836 /* assign the amsops */
3837 aopOp (left, ic, FALSE);
3838 aopOp (right, ic, FALSE);
3839 aopOp (result, ic, TRUE);
3841 genCmp (right, left, result, ifx, sign);
3843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3845 freeAsmop (result, NULL, ic, TRUE);
3848 /*-----------------------------------------------------------------*/
3849 /* genCmpLt - less than comparisons */
3850 /*-----------------------------------------------------------------*/
3852 genCmpLt (iCode * ic, iCode * ifx)
3854 operand *left, *right, *result;
3855 sym_link *letype, *retype;
3858 left = IC_LEFT (ic);
3859 right = IC_RIGHT (ic);
3860 result = IC_RESULT (ic);
3862 letype = getSpec (operandType (left));
3863 retype = getSpec (operandType (right));
3864 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3866 /* assign the amsops */
3867 aopOp (left, ic, FALSE);
3868 aopOp (right, ic, FALSE);
3869 aopOp (result, ic, TRUE);
3871 genCmp (left, right, result, ifx, sign);
3873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3875 freeAsmop (result, NULL, ic, TRUE);
3878 /*-----------------------------------------------------------------*/
3879 /* gencjneshort - compare and jump if not equal */
3880 /*-----------------------------------------------------------------*/
3882 gencjneshort (operand * left, operand * right, symbol * lbl)
3884 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3886 unsigned long lit = 0L;
3888 /* if the left side is a literal or
3889 if the right is in a pointer register and left
3891 if ((AOP_TYPE (left) == AOP_LIT) ||
3892 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3898 if (AOP_TYPE (right) == AOP_LIT)
3899 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3901 /* if the right side is a literal then anything goes */
3902 if (AOP_TYPE (right) == AOP_LIT &&
3903 AOP_TYPE (left) != AOP_DIR)
3907 emitcode ("cjne", "%s,%s,%05d$",
3908 aopGet (AOP (left), offset, FALSE, FALSE),
3909 aopGet (AOP (right), offset, FALSE, FALSE),
3915 /* if the right side is in a register or in direct space or
3916 if the left is a pointer register & right is not */
3917 else if (AOP_TYPE (right) == AOP_REG ||
3918 AOP_TYPE (right) == AOP_DIR ||
3919 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3920 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3924 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3925 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3926 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3927 emitcode ("jnz", "%05d$", lbl->key + 100);
3929 emitcode ("cjne", "a,%s,%05d$",
3930 aopGet (AOP (right), offset, FALSE, TRUE),
3937 /* right is a pointer reg need both a & b */
3940 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3941 if (strcmp (l, "b"))
3942 emitcode ("mov", "b,%s", l);
3943 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3944 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3950 /*-----------------------------------------------------------------*/
3951 /* gencjne - compare and jump if not equal */
3952 /*-----------------------------------------------------------------*/
3954 gencjne (operand * left, operand * right, symbol * lbl)
3956 symbol *tlbl = newiTempLabel (NULL);
3958 gencjneshort (left, right, lbl);
3960 emitcode ("mov", "a,%s", one);
3961 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3962 emitcode ("", "%05d$:", lbl->key + 100);
3963 emitcode ("clr", "a");
3964 emitcode ("", "%05d$:", tlbl->key + 100);
3967 /*-----------------------------------------------------------------*/
3968 /* genCmpEq - generates code for equal to */
3969 /*-----------------------------------------------------------------*/
3971 genCmpEq (iCode * ic, iCode * ifx)
3973 operand *left, *right, *result;
3975 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3976 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3977 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3979 /* if literal, literal on the right or
3980 if the right is in a pointer register and left
3982 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3983 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3985 operand *t = IC_RIGHT (ic);
3986 IC_RIGHT (ic) = IC_LEFT (ic);
3990 if (ifx && !AOP_SIZE (result))
3993 /* if they are both bit variables */
3994 if (AOP_TYPE (left) == AOP_CRY &&
3995 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3997 if (AOP_TYPE (right) == AOP_LIT)
3999 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4002 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4003 emitcode ("cpl", "c");
4007 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4011 emitcode ("clr", "c");
4013 /* AOP_TYPE(right) == AOP_CRY */
4017 symbol *lbl = newiTempLabel (NULL);
4018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4019 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4020 emitcode ("cpl", "c");
4021 emitcode ("", "%05d$:", (lbl->key + 100));
4023 /* if true label then we jump if condition
4025 tlbl = newiTempLabel (NULL);
4028 emitcode ("jnc", "%05d$", tlbl->key + 100);
4029 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4033 emitcode ("jc", "%05d$", tlbl->key + 100);
4034 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4036 emitcode ("", "%05d$:", tlbl->key + 100);
4040 tlbl = newiTempLabel (NULL);
4041 gencjneshort (left, right, tlbl);
4044 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4045 emitcode ("", "%05d$:", tlbl->key + 100);
4049 symbol *lbl = newiTempLabel (NULL);
4050 emitcode ("sjmp", "%05d$", lbl->key + 100);
4051 emitcode ("", "%05d$:", tlbl->key + 100);
4052 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4053 emitcode ("", "%05d$:", lbl->key + 100);
4056 /* mark the icode as generated */
4061 /* if they are both bit variables */
4062 if (AOP_TYPE (left) == AOP_CRY &&
4063 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4065 if (AOP_TYPE (right) == AOP_LIT)
4067 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4070 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4071 emitcode ("cpl", "c");
4075 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4079 emitcode ("clr", "c");
4081 /* AOP_TYPE(right) == AOP_CRY */
4085 symbol *lbl = newiTempLabel (NULL);
4086 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4087 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4088 emitcode ("cpl", "c");
4089 emitcode ("", "%05d$:", (lbl->key + 100));
4092 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4099 genIfxJump (ifx, "c");
4102 /* if the result is used in an arithmetic operation
4103 then put the result in place */
4108 gencjne (left, right, newiTempLabel (NULL));
4109 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4111 aopPut (AOP (result), "a", 0);
4116 genIfxJump (ifx, "a");
4119 /* if the result is used in an arithmetic operation
4120 then put the result in place */
4121 if (AOP_TYPE (result) != AOP_CRY)
4123 /* leave the result in acc */
4127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (result, NULL, ic, TRUE);
4132 /*-----------------------------------------------------------------*/
4133 /* ifxForOp - returns the icode containing the ifx for operand */
4134 /*-----------------------------------------------------------------*/
4136 ifxForOp (operand * op, iCode * ic)
4138 /* if true symbol then needs to be assigned */
4139 if (IS_TRUE_SYMOP (op))
4142 /* if this has register type condition and
4143 the next instruction is ifx with the same operand
4144 and live to of the operand is upto the ifx only then */
4146 ic->next->op == IFX &&
4147 IC_COND (ic->next)->key == op->key &&
4148 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4153 /*-----------------------------------------------------------------*/
4154 /* genAndOp - for && operation */
4155 /*-----------------------------------------------------------------*/
4157 genAndOp (iCode * ic)
4159 operand *left, *right, *result;
4162 /* note here that && operations that are in an
4163 if statement are taken away by backPatchLabels
4164 only those used in arthmetic operations remain */
4165 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4166 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4167 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4169 /* if both are bit variables */
4170 if (AOP_TYPE (left) == AOP_CRY &&
4171 AOP_TYPE (right) == AOP_CRY)
4173 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4174 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4179 tlbl = newiTempLabel (NULL);
4181 emitcode ("jz", "%05d$", tlbl->key + 100);
4183 emitcode ("", "%05d$:", tlbl->key + 100);
4187 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4188 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4189 freeAsmop (result, NULL, ic, TRUE);
4193 /*-----------------------------------------------------------------*/
4194 /* genOrOp - for || operation */
4195 /*-----------------------------------------------------------------*/
4197 genOrOp (iCode * ic)
4199 operand *left, *right, *result;
4202 /* note here that || operations that are in an
4203 if statement are taken away by backPatchLabels
4204 only those used in arthmetic operations remain */
4205 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4206 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4207 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4209 /* if both are bit variables */
4210 if (AOP_TYPE (left) == AOP_CRY &&
4211 AOP_TYPE (right) == AOP_CRY)
4213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4214 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4219 tlbl = newiTempLabel (NULL);
4221 emitcode ("jnz", "%05d$", tlbl->key + 100);
4223 emitcode ("", "%05d$:", tlbl->key + 100);
4227 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4228 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4229 freeAsmop (result, NULL, ic, TRUE);
4232 /*-----------------------------------------------------------------*/
4233 /* isLiteralBit - test if lit == 2^n */
4234 /*-----------------------------------------------------------------*/
4236 isLiteralBit (unsigned long lit)
4238 unsigned long pw[32] =
4239 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4240 0x100L, 0x200L, 0x400L, 0x800L,
4241 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4242 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4243 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4244 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4245 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4248 for (idx = 0; idx < 32; idx++)
4254 /*-----------------------------------------------------------------*/
4255 /* continueIfTrue - */
4256 /*-----------------------------------------------------------------*/
4258 continueIfTrue (iCode * ic)
4261 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4265 /*-----------------------------------------------------------------*/
4267 /*-----------------------------------------------------------------*/
4269 jumpIfTrue (iCode * ic)
4272 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4276 /*-----------------------------------------------------------------*/
4277 /* jmpTrueOrFalse - */
4278 /*-----------------------------------------------------------------*/
4280 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4282 // ugly but optimized by peephole
4285 symbol *nlbl = newiTempLabel (NULL);
4286 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4287 emitcode ("", "%05d$:", tlbl->key + 100);
4288 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4289 emitcode ("", "%05d$:", nlbl->key + 100);
4293 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4294 emitcode ("", "%05d$:", tlbl->key + 100);
4299 /*-----------------------------------------------------------------*/
4300 /* genAnd - code for and */
4301 /*-----------------------------------------------------------------*/
4303 genAnd (iCode * ic, iCode * ifx)
4305 operand *left, *right, *result;
4306 int size, offset = 0;
4307 unsigned long lit = 0L;
4311 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4312 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4313 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4316 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4318 AOP_TYPE (left), AOP_TYPE (right));
4319 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4321 AOP_SIZE (left), AOP_SIZE (right));
4324 /* if left is a literal & right is not then exchange them */
4325 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4326 AOP_NEEDSACC (left))
4328 operand *tmp = right;
4333 /* if result = right then exchange them */
4334 if (sameRegs (AOP (result), AOP (right)))
4336 operand *tmp = right;
4341 /* if right is bit then exchange them */
4342 if (AOP_TYPE (right) == AOP_CRY &&
4343 AOP_TYPE (left) != AOP_CRY)
4345 operand *tmp = right;
4349 if (AOP_TYPE (right) == AOP_LIT)
4350 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4352 size = AOP_SIZE (result);
4355 // result = bit & yy;
4356 if (AOP_TYPE (left) == AOP_CRY)
4358 // c = bit & literal;
4359 if (AOP_TYPE (right) == AOP_LIT)
4363 if (size && sameRegs (AOP (result), AOP (left)))
4366 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4371 if (size && (AOP_TYPE (result) == AOP_CRY))
4373 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4376 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4381 emitcode ("clr", "c");
4386 if (AOP_TYPE (right) == AOP_CRY)
4389 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4390 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4395 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4397 emitcode ("rrc", "a");
4398 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4406 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4407 genIfxJump (ifx, "c");
4411 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4412 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4413 if ((AOP_TYPE (right) == AOP_LIT) &&
4414 (AOP_TYPE (result) == AOP_CRY) &&
4415 (AOP_TYPE (left) != AOP_CRY))
4417 int posbit = isLiteralBit (lit);
4422 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4425 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4431 sprintf (buffer, "acc.%d", posbit & 0x07);
4432 genIfxJump (ifx, buffer);
4439 symbol *tlbl = newiTempLabel (NULL);
4440 int sizel = AOP_SIZE (left);
4442 emitcode ("setb", "c");
4445 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4447 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4449 if ((posbit = isLiteralBit (bytelit)) != 0)
4450 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4453 if (bytelit != 0x0FFL)
4454 emitcode ("anl", "a,%s",
4455 aopGet (AOP (right), offset, FALSE, TRUE));
4456 emitcode ("jnz", "%05d$", tlbl->key + 100);
4461 // bit = left & literal
4464 emitcode ("clr", "c");
4465 emitcode ("", "%05d$:", tlbl->key + 100);
4467 // if(left & literal)
4471 jmpTrueOrFalse (ifx, tlbl);
4479 /* if left is same as result */
4480 if (sameRegs (AOP (result), AOP (left)))
4482 for (; size--; offset++)
4484 if (AOP_TYPE (right) == AOP_LIT)
4486 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4488 else if (bytelit == 0)
4489 aopPut (AOP (result), zero, offset);
4490 else if (IS_AOP_PREG (result))
4492 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4493 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4494 aopPut (AOP (result), "a", offset);
4497 emitcode ("anl", "%s,%s",
4498 aopGet (AOP (left), offset, FALSE, TRUE),
4499 aopGet (AOP (right), offset, FALSE, FALSE));
4503 if (AOP_TYPE (left) == AOP_ACC)
4504 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4507 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4508 if (IS_AOP_PREG (result))
4510 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4511 aopPut (AOP (result), "a", offset);
4515 emitcode ("anl", "%s,a",
4516 aopGet (AOP (left), offset, FALSE, TRUE));
4523 // left & result in different registers
4524 if (AOP_TYPE (result) == AOP_CRY)
4527 // if(size), result in bit
4528 // if(!size && ifx), conditional oper: if(left & right)
4529 symbol *tlbl = newiTempLabel (NULL);
4530 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4532 emitcode ("setb", "c");
4535 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4536 emitcode ("anl", "a,%s",
4537 aopGet (AOP (left), offset, FALSE, FALSE));
4538 emitcode ("jnz", "%05d$", tlbl->key + 100);
4544 emitcode ("", "%05d$:", tlbl->key + 100);
4548 jmpTrueOrFalse (ifx, tlbl);
4552 for (; (size--); offset++)
4555 // result = left & right
4556 if (AOP_TYPE (right) == AOP_LIT)
4558 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4560 aopPut (AOP (result),
4561 aopGet (AOP (left), offset, FALSE, FALSE),
4565 else if (bytelit == 0)
4567 aopPut (AOP (result), zero, offset);
4571 // faster than result <- left, anl result,right
4572 // and better if result is SFR
4573 if (AOP_TYPE (left) == AOP_ACC)
4574 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4577 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4578 emitcode ("anl", "a,%s",
4579 aopGet (AOP (left), offset, FALSE, FALSE));
4581 aopPut (AOP (result), "a", offset);
4587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4588 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589 freeAsmop (result, NULL, ic, TRUE);
4592 /*-----------------------------------------------------------------*/
4593 /* genOr - code for or */
4594 /*-----------------------------------------------------------------*/
4596 genOr (iCode * ic, iCode * ifx)
4598 operand *left, *right, *result;
4599 int size, offset = 0;
4600 unsigned long lit = 0L;
4602 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4603 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4604 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4607 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4609 AOP_TYPE (left), AOP_TYPE (right));
4610 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4612 AOP_SIZE (left), AOP_SIZE (right));
4615 /* if left is a literal & right is not then exchange them */
4616 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4617 AOP_NEEDSACC (left))
4619 operand *tmp = right;
4624 /* if result = right then exchange them */
4625 if (sameRegs (AOP (result), AOP (right)))
4627 operand *tmp = right;
4632 /* if right is bit then exchange them */
4633 if (AOP_TYPE (right) == AOP_CRY &&
4634 AOP_TYPE (left) != AOP_CRY)
4636 operand *tmp = right;
4640 if (AOP_TYPE (right) == AOP_LIT)
4641 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4643 size = AOP_SIZE (result);
4647 if (AOP_TYPE (left) == AOP_CRY)
4649 if (AOP_TYPE (right) == AOP_LIT)
4651 // c = bit & literal;
4654 // lit != 0 => result = 1
4655 if (AOP_TYPE (result) == AOP_CRY)
4658 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4660 continueIfTrue (ifx);
4663 emitcode ("setb", "c");
4667 // lit == 0 => result = left
4668 if (size && sameRegs (AOP (result), AOP (left)))
4670 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4675 if (AOP_TYPE (right) == AOP_CRY)
4678 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4679 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4684 symbol *tlbl = newiTempLabel (NULL);
4685 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4686 emitcode ("setb", "c");
4687 emitcode ("jb", "%s,%05d$",
4688 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4690 emitcode ("jnz", "%05d$", tlbl->key + 100);
4691 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4693 jmpTrueOrFalse (ifx, tlbl);
4699 emitcode ("", "%05d$:", tlbl->key + 100);
4708 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4709 genIfxJump (ifx, "c");
4713 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4714 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4715 if ((AOP_TYPE (right) == AOP_LIT) &&
4716 (AOP_TYPE (result) == AOP_CRY) &&
4717 (AOP_TYPE (left) != AOP_CRY))
4723 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4725 continueIfTrue (ifx);
4730 // lit = 0, result = boolean(left)
4732 emitcode ("setb", "c");
4736 symbol *tlbl = newiTempLabel (NULL);
4737 emitcode ("jnz", "%05d$", tlbl->key + 100);
4739 emitcode ("", "%05d$:", tlbl->key + 100);
4743 genIfxJump (ifx, "a");
4751 /* if left is same as result */
4752 if (sameRegs (AOP (result), AOP (left)))
4754 for (; size--; offset++)
4756 if (AOP_TYPE (right) == AOP_LIT)
4758 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4760 else if (IS_AOP_PREG (left))
4762 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4763 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4764 aopPut (AOP (result), "a", offset);
4767 emitcode ("orl", "%s,%s",
4768 aopGet (AOP (left), offset, FALSE, TRUE),
4769 aopGet (AOP (right), offset, FALSE, FALSE));
4773 if (AOP_TYPE (left) == AOP_ACC)
4774 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4777 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4778 if (IS_AOP_PREG (left))
4780 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4781 aopPut (AOP (result), "a", offset);
4784 emitcode ("orl", "%s,a",
4785 aopGet (AOP (left), offset, FALSE, TRUE));
4792 // left & result in different registers
4793 if (AOP_TYPE (result) == AOP_CRY)
4796 // if(size), result in bit
4797 // if(!size && ifx), conditional oper: if(left | right)
4798 symbol *tlbl = newiTempLabel (NULL);
4799 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4801 emitcode ("setb", "c");
4804 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4805 emitcode ("orl", "a,%s",
4806 aopGet (AOP (left), offset, FALSE, FALSE));
4807 emitcode ("jnz", "%05d$", tlbl->key + 100);
4813 emitcode ("", "%05d$:", tlbl->key + 100);
4817 jmpTrueOrFalse (ifx, tlbl);
4820 for (; (size--); offset++)
4823 // result = left & right
4824 if (AOP_TYPE (right) == AOP_LIT)
4826 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4828 aopPut (AOP (result),
4829 aopGet (AOP (left), offset, FALSE, FALSE),
4834 // faster than result <- left, anl result,right
4835 // and better if result is SFR
4836 if (AOP_TYPE (left) == AOP_ACC)
4837 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4840 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4841 emitcode ("orl", "a,%s",
4842 aopGet (AOP (left), offset, FALSE, FALSE));
4844 aopPut (AOP (result), "a", offset);
4849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 freeAsmop (result, NULL, ic, TRUE);
4854 /*-----------------------------------------------------------------*/
4855 /* genXor - code for xclusive or */
4856 /*-----------------------------------------------------------------*/
4858 genXor (iCode * ic, iCode * ifx)
4860 operand *left, *right, *result;
4861 int size, offset = 0;
4862 unsigned long lit = 0L;
4864 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4865 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4866 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4869 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4871 AOP_TYPE (left), AOP_TYPE (right));
4872 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4874 AOP_SIZE (left), AOP_SIZE (right));
4877 /* if left is a literal & right is not ||
4878 if left needs acc & right does not */
4879 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4880 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4882 operand *tmp = right;
4887 /* if result = right then exchange them */
4888 if (sameRegs (AOP (result), AOP (right)))
4890 operand *tmp = right;
4895 /* if right is bit then exchange them */
4896 if (AOP_TYPE (right) == AOP_CRY &&
4897 AOP_TYPE (left) != AOP_CRY)
4899 operand *tmp = right;
4903 if (AOP_TYPE (right) == AOP_LIT)
4904 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4906 size = AOP_SIZE (result);
4910 if (AOP_TYPE (left) == AOP_CRY)
4912 if (AOP_TYPE (right) == AOP_LIT)
4914 // c = bit & literal;
4917 // lit>>1 != 0 => result = 1
4918 if (AOP_TYPE (result) == AOP_CRY)
4921 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4923 continueIfTrue (ifx);
4926 emitcode ("setb", "c");
4933 // lit == 0, result = left
4934 if (size && sameRegs (AOP (result), AOP (left)))
4936 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4940 // lit == 1, result = not(left)
4941 if (size && sameRegs (AOP (result), AOP (left)))
4943 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4949 emitcode ("cpl", "c");
4958 symbol *tlbl = newiTempLabel (NULL);
4959 if (AOP_TYPE (right) == AOP_CRY)
4962 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4966 int sizer = AOP_SIZE (right);
4968 // if val>>1 != 0, result = 1
4969 emitcode ("setb", "c");
4972 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4974 // test the msb of the lsb
4975 emitcode ("anl", "a,#0xfe");
4976 emitcode ("jnz", "%05d$", tlbl->key + 100);
4980 emitcode ("rrc", "a");
4982 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4983 emitcode ("cpl", "c");
4984 emitcode ("", "%05d$:", (tlbl->key + 100));
4991 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4992 genIfxJump (ifx, "c");
4996 if (sameRegs (AOP (result), AOP (left)))
4998 /* if left is same as result */
4999 for (; size--; offset++)
5001 if (AOP_TYPE (right) == AOP_LIT)
5003 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5005 else if (IS_AOP_PREG (left))
5007 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5008 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5009 aopPut (AOP (result), "a", offset);
5012 emitcode ("xrl", "%s,%s",
5013 aopGet (AOP (left), offset, FALSE, TRUE),
5014 aopGet (AOP (right), offset, FALSE, FALSE));
5018 if (AOP_TYPE (left) == AOP_ACC)
5019 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5022 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5023 if (IS_AOP_PREG (left))
5025 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5026 aopPut (AOP (result), "a", offset);
5029 emitcode ("xrl", "%s,a",
5030 aopGet (AOP (left), offset, FALSE, TRUE));
5037 // left & result in different registers
5038 if (AOP_TYPE (result) == AOP_CRY)
5041 // if(size), result in bit
5042 // if(!size && ifx), conditional oper: if(left ^ right)
5043 symbol *tlbl = newiTempLabel (NULL);
5044 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5046 emitcode ("setb", "c");
5049 if ((AOP_TYPE (right) == AOP_LIT) &&
5050 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5052 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5056 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5057 emitcode ("xrl", "a,%s",
5058 aopGet (AOP (left), offset, FALSE, FALSE));
5060 emitcode ("jnz", "%05d$", tlbl->key + 100);
5066 emitcode ("", "%05d$:", tlbl->key + 100);
5070 jmpTrueOrFalse (ifx, tlbl);
5073 for (; (size--); offset++)
5076 // result = left & right
5077 if (AOP_TYPE (right) == AOP_LIT)
5079 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5081 aopPut (AOP (result),
5082 aopGet (AOP (left), offset, FALSE, FALSE),
5087 // faster than result <- left, anl result,right
5088 // and better if result is SFR
5089 if (AOP_TYPE (left) == AOP_ACC)
5090 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5093 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5094 emitcode ("xrl", "a,%s",
5095 aopGet (AOP (left), offset, FALSE, TRUE));
5097 aopPut (AOP (result), "a", offset);
5102 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5103 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5104 freeAsmop (result, NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* genInline - write the inline code out */
5109 /*-----------------------------------------------------------------*/
5111 genInline (iCode * ic)
5113 char buffer[MAX_INLINEASM];
5117 _G.inLine += (!options.asmpeep);
5118 strcpy (buffer, IC_INLINE (ic));
5120 /* emit each line as a code */
5145 /* emitcode("",buffer); */
5146 _G.inLine -= (!options.asmpeep);
5149 /*-----------------------------------------------------------------*/
5150 /* genRRC - rotate right with carry */
5151 /*-----------------------------------------------------------------*/
5155 operand *left, *result;
5156 int size, offset = 0;
5159 /* rotate right with carry */
5160 left = IC_LEFT (ic);
5161 result = IC_RESULT (ic);
5162 aopOp (left, ic, FALSE);
5163 aopOp (result, ic, FALSE);
5165 /* move it to the result */
5166 size = AOP_SIZE (result);
5171 l = aopGet (AOP (left), offset, FALSE, FALSE);
5173 emitcode ("rrc", "a");
5174 if (AOP_SIZE (result) > 1)
5175 aopPut (AOP (result), "a", offset--);
5177 /* now we need to put the carry into the
5178 highest order byte of the result */
5179 if (AOP_SIZE (result) > 1)
5181 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5184 emitcode ("mov", "acc.7,c");
5185 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5186 freeAsmop (left, NULL, ic, TRUE);
5187 freeAsmop (result, NULL, ic, TRUE);
5190 /*-----------------------------------------------------------------*/
5191 /* genRLC - generate code for rotate left with carry */
5192 /*-----------------------------------------------------------------*/
5196 operand *left, *result;
5197 int size, offset = 0;
5200 /* rotate right with carry */
5201 left = IC_LEFT (ic);
5202 result = IC_RESULT (ic);
5203 aopOp (left, ic, FALSE);
5204 aopOp (result, ic, FALSE);
5206 /* move it to the result */
5207 size = AOP_SIZE (result);
5211 l = aopGet (AOP (left), offset, FALSE, FALSE);
5213 emitcode ("add", "a,acc");
5214 if (AOP_SIZE (result) > 1)
5215 aopPut (AOP (result), "a", offset++);
5218 l = aopGet (AOP (left), offset, FALSE, FALSE);
5220 emitcode ("rlc", "a");
5221 if (AOP_SIZE (result) > 1)
5222 aopPut (AOP (result), "a", offset++);
5225 /* now we need to put the carry into the
5226 highest order byte of the result */
5227 if (AOP_SIZE (result) > 1)
5229 l = aopGet (AOP (result), 0, FALSE, FALSE);
5232 emitcode ("mov", "acc.0,c");
5233 aopPut (AOP (result), "a", 0);
5234 freeAsmop (left, NULL, ic, TRUE);
5235 freeAsmop (result, NULL, ic, TRUE);
5238 /*-----------------------------------------------------------------*/
5239 /* genGetHbit - generates code get highest order bit */
5240 /*-----------------------------------------------------------------*/
5242 genGetHbit (iCode * ic)
5244 operand *left, *result;
5245 left = IC_LEFT (ic);
5246 result = IC_RESULT (ic);
5247 aopOp (left, ic, FALSE);
5248 aopOp (result, ic, FALSE);
5250 /* get the highest order byte into a */
5251 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5252 if (AOP_TYPE (result) == AOP_CRY)
5254 emitcode ("rlc", "a");
5259 emitcode ("rl", "a");
5260 emitcode ("anl", "a,#0x01");
5265 freeAsmop (left, NULL, ic, TRUE);
5266 freeAsmop (result, NULL, ic, TRUE);
5269 /*-----------------------------------------------------------------*/
5270 /* AccRol - rotate left accumulator by known count */
5271 /*-----------------------------------------------------------------*/
5273 AccRol (int shCount)
5275 shCount &= 0x0007; // shCount : 0..7
5282 emitcode ("rl", "a");
5285 emitcode ("rl", "a");
5286 emitcode ("rl", "a");
5289 emitcode ("swap", "a");
5290 emitcode ("rr", "a");
5293 emitcode ("swap", "a");
5296 emitcode ("swap", "a");
5297 emitcode ("rl", "a");
5300 emitcode ("rr", "a");
5301 emitcode ("rr", "a");
5304 emitcode ("rr", "a");
5309 /*-----------------------------------------------------------------*/
5310 /* AccLsh - left shift accumulator by known count */
5311 /*-----------------------------------------------------------------*/
5313 AccLsh (int shCount)
5318 emitcode ("add", "a,acc");
5319 else if (shCount == 2)
5321 emitcode ("add", "a,acc");
5322 emitcode ("add", "a,acc");
5326 /* rotate left accumulator */
5328 /* and kill the lower order bits */
5329 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5334 /*-----------------------------------------------------------------*/
5335 /* AccRsh - right shift accumulator by known count */
5336 /*-----------------------------------------------------------------*/
5338 AccRsh (int shCount)
5345 emitcode ("rrc", "a");
5349 /* rotate right accumulator */
5350 AccRol (8 - shCount);
5351 /* and kill the higher order bits */
5352 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5357 /*-----------------------------------------------------------------*/
5358 /* AccSRsh - signed right shift accumulator by known count */
5359 /*-----------------------------------------------------------------*/
5361 AccSRsh (int shCount)
5368 emitcode ("mov", "c,acc.7");
5369 emitcode ("rrc", "a");
5371 else if (shCount == 2)
5373 emitcode ("mov", "c,acc.7");
5374 emitcode ("rrc", "a");
5375 emitcode ("mov", "c,acc.7");
5376 emitcode ("rrc", "a");
5380 tlbl = newiTempLabel (NULL);
5381 /* rotate right accumulator */
5382 AccRol (8 - shCount);
5383 /* and kill the higher order bits */
5384 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5385 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5386 emitcode ("orl", "a,#0x%02x",
5387 (unsigned char) ~SRMask[shCount]);
5388 emitcode ("", "%05d$:", tlbl->key + 100);
5393 /*-----------------------------------------------------------------*/
5394 /* shiftR1Left2Result - shift right one byte from left to result */
5395 /*-----------------------------------------------------------------*/
5397 shiftR1Left2Result (operand * left, int offl,
5398 operand * result, int offr,
5399 int shCount, int sign)
5401 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5402 /* shift right accumulator */
5407 aopPut (AOP (result), "a", offr);
5410 /*-----------------------------------------------------------------*/
5411 /* shiftL1Left2Result - shift left one byte from left to result */
5412 /*-----------------------------------------------------------------*/
5414 shiftL1Left2Result (operand * left, int offl,
5415 operand * result, int offr, int shCount)
5418 l = aopGet (AOP (left), offl, FALSE, FALSE);
5420 /* shift left accumulator */
5422 aopPut (AOP (result), "a", offr);
5425 /*-----------------------------------------------------------------*/
5426 /* movLeft2Result - move byte from left to result */
5427 /*-----------------------------------------------------------------*/
5429 movLeft2Result (operand * left, int offl,
5430 operand * result, int offr, int sign)
5433 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5435 l = aopGet (AOP (left), offl, FALSE, FALSE);
5437 if (*l == '@' && (IS_AOP_PREG (result)))
5439 emitcode ("mov", "a,%s", l);
5440 aopPut (AOP (result), "a", offr);
5445 aopPut (AOP (result), l, offr);
5448 /* MSB sign in acc.7 ! */
5449 if (getDataSize (left) == offl + 1)
5451 emitcode ("mov", "a,%s", l);
5452 aopPut (AOP (result), "a", offr);
5459 /*-----------------------------------------------------------------*/
5460 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5461 /*-----------------------------------------------------------------*/
5465 emitcode ("rrc", "a");
5466 emitcode ("xch", "a,%s", x);
5467 emitcode ("rrc", "a");
5468 emitcode ("xch", "a,%s", x);
5471 /*-----------------------------------------------------------------*/
5472 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5473 /*-----------------------------------------------------------------*/
5477 emitcode ("xch", "a,%s", x);
5478 emitcode ("rlc", "a");
5479 emitcode ("xch", "a,%s", x);
5480 emitcode ("rlc", "a");
5483 /*-----------------------------------------------------------------*/
5484 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5485 /*-----------------------------------------------------------------*/
5489 emitcode ("xch", "a,%s", x);
5490 emitcode ("add", "a,acc");
5491 emitcode ("xch", "a,%s", x);
5492 emitcode ("rlc", "a");
5495 /*-----------------------------------------------------------------*/
5496 /* AccAXLsh - left shift a:x by known count (0..7) */
5497 /*-----------------------------------------------------------------*/
5499 AccAXLsh (char *x, int shCount)
5514 case 5: // AAAAABBB:CCCCCDDD
5516 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5518 emitcode ("anl", "a,#0x%02x",
5519 SLMask[shCount]); // BBB00000:CCCCCDDD
5521 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5523 AccRol (shCount); // DDDCCCCC:BBB00000
5525 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5527 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5529 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5531 emitcode ("anl", "a,#0x%02x",
5532 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5534 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5536 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5539 case 6: // AAAAAABB:CCCCCCDD
5540 emitcode ("anl", "a,#0x%02x",
5541 SRMask[shCount]); // 000000BB:CCCCCCDD
5542 emitcode ("mov", "c,acc.0"); // c = B
5543 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5545 AccAXRrl1 (x); // BCCCCCCD:D000000B
5546 AccAXRrl1 (x); // BBCCCCCC:DD000000
5548 emitcode("rrc","a");
5549 emitcode("xch","a,%s", x);
5550 emitcode("rrc","a");
5551 emitcode("mov","c,acc.0"); //<< get correct bit
5552 emitcode("xch","a,%s", x);
5554 emitcode("rrc","a");
5555 emitcode("xch","a,%s", x);
5556 emitcode("rrc","a");
5557 emitcode("xch","a,%s", x);
5560 case 7: // a:x <<= 7
5562 emitcode ("anl", "a,#0x%02x",
5563 SRMask[shCount]); // 0000000B:CCCCCCCD
5565 emitcode ("mov", "c,acc.0"); // c = B
5567 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5569 AccAXRrl1 (x); // BCCCCCCC:D0000000
5577 /*-----------------------------------------------------------------*/
5578 /* AccAXRsh - right shift a:x known count (0..7) */
5579 /*-----------------------------------------------------------------*/
5581 AccAXRsh (char *x, int shCount)
5589 AccAXRrl1 (x); // 0->a:x
5594 AccAXRrl1 (x); // 0->a:x
5597 AccAXRrl1 (x); // 0->a:x
5602 case 5: // AAAAABBB:CCCCCDDD = a:x
5604 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5606 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5608 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5610 emitcode ("anl", "a,#0x%02x",
5611 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5613 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5615 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5617 emitcode ("anl", "a,#0x%02x",
5618 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5620 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5622 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5624 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5627 case 6: // AABBBBBB:CCDDDDDD
5629 emitcode ("mov", "c,acc.7");
5630 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5632 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5634 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5636 emitcode ("anl", "a,#0x%02x",
5637 SRMask[shCount]); // 000000AA:BBBBBBCC
5640 case 7: // ABBBBBBB:CDDDDDDD
5642 emitcode ("mov", "c,acc.7"); // c = A
5644 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5646 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5648 emitcode ("anl", "a,#0x%02x",
5649 SRMask[shCount]); // 0000000A:BBBBBBBC
5657 /*-----------------------------------------------------------------*/
5658 /* AccAXRshS - right shift signed a:x known count (0..7) */
5659 /*-----------------------------------------------------------------*/
5661 AccAXRshS (char *x, int shCount)
5669 emitcode ("mov", "c,acc.7");
5670 AccAXRrl1 (x); // s->a:x
5674 emitcode ("mov", "c,acc.7");
5675 AccAXRrl1 (x); // s->a:x
5677 emitcode ("mov", "c,acc.7");
5678 AccAXRrl1 (x); // s->a:x
5683 case 5: // AAAAABBB:CCCCCDDD = a:x
5685 tlbl = newiTempLabel (NULL);
5686 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5688 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5690 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5692 emitcode ("anl", "a,#0x%02x",
5693 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5695 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5697 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5699 emitcode ("anl", "a,#0x%02x",
5700 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5702 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5704 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5706 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5708 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5709 emitcode ("orl", "a,#0x%02x",
5710 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5712 emitcode ("", "%05d$:", tlbl->key + 100);
5713 break; // SSSSAAAA:BBBCCCCC
5715 case 6: // AABBBBBB:CCDDDDDD
5717 tlbl = newiTempLabel (NULL);
5718 emitcode ("mov", "c,acc.7");
5719 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5721 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5723 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5725 emitcode ("anl", "a,#0x%02x",
5726 SRMask[shCount]); // 000000AA:BBBBBBCC
5728 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5729 emitcode ("orl", "a,#0x%02x",
5730 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5732 emitcode ("", "%05d$:", tlbl->key + 100);
5734 case 7: // ABBBBBBB:CDDDDDDD
5736 tlbl = newiTempLabel (NULL);
5737 emitcode ("mov", "c,acc.7"); // c = A
5739 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5741 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5743 emitcode ("anl", "a,#0x%02x",
5744 SRMask[shCount]); // 0000000A:BBBBBBBC
5746 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5747 emitcode ("orl", "a,#0x%02x",
5748 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5750 emitcode ("", "%05d$:", tlbl->key + 100);
5757 /*-----------------------------------------------------------------*/
5758 /* shiftL2Left2Result - shift left two bytes from left to result */
5759 /*-----------------------------------------------------------------*/
5761 shiftL2Left2Result (operand * left, int offl,
5762 operand * result, int offr, int shCount)
5764 if (sameRegs (AOP (result), AOP (left)) &&
5765 ((offl + MSB16) == offr))
5767 /* don't crash result[offr] */
5768 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5769 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5773 movLeft2Result (left, offl, result, offr, 0);
5774 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5776 /* ax << shCount (x = lsb(result)) */
5777 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5778 aopPut (AOP (result), "a", offr + MSB16);
5782 /*-----------------------------------------------------------------*/
5783 /* shiftR2Left2Result - shift right two bytes from left to result */
5784 /*-----------------------------------------------------------------*/
5786 shiftR2Left2Result (operand * left, int offl,
5787 operand * result, int offr,
5788 int shCount, int sign)
5790 if (sameRegs (AOP (result), AOP (left)) &&
5791 ((offl + MSB16) == offr))
5793 /* don't crash result[offr] */
5794 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5795 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5799 movLeft2Result (left, offl, result, offr, 0);
5800 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5802 /* a:x >> shCount (x = lsb(result)) */
5804 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5806 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5807 if (getDataSize (result) > 1)
5808 aopPut (AOP (result), "a", offr + MSB16);
5811 /*-----------------------------------------------------------------*/
5812 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5813 /*-----------------------------------------------------------------*/
5815 shiftLLeftOrResult (operand * left, int offl,
5816 operand * result, int offr, int shCount)
5818 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5819 /* shift left accumulator */
5821 /* or with result */
5822 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5823 /* back to result */
5824 aopPut (AOP (result), "a", offr);
5827 /*-----------------------------------------------------------------*/
5828 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5829 /*-----------------------------------------------------------------*/
5831 shiftRLeftOrResult (operand * left, int offl,
5832 operand * result, int offr, int shCount)
5834 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5835 /* shift right accumulator */
5837 /* or with result */
5838 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5839 /* back to result */
5840 aopPut (AOP (result), "a", offr);
5843 /*-----------------------------------------------------------------*/
5844 /* genlshOne - left shift a one byte quantity by known count */
5845 /*-----------------------------------------------------------------*/
5847 genlshOne (operand * result, operand * left, int shCount)
5849 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5852 /*-----------------------------------------------------------------*/
5853 /* genlshTwo - left shift two bytes by known amount != 0 */
5854 /*-----------------------------------------------------------------*/
5856 genlshTwo (operand * result, operand * left, int shCount)
5860 size = getDataSize (result);
5862 /* if shCount >= 8 */
5870 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5872 movLeft2Result (left, LSB, result, MSB16, 0);
5874 aopPut (AOP (result), zero, LSB);
5877 /* 1 <= shCount <= 7 */
5881 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5883 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5887 /*-----------------------------------------------------------------*/
5888 /* shiftLLong - shift left one long from left to result */
5889 /* offl = LSB or MSB16 */
5890 /*-----------------------------------------------------------------*/
5892 shiftLLong (operand * left, operand * result, int offr)
5895 int size = AOP_SIZE (result);
5897 if (size >= LSB + offr)
5899 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5901 emitcode ("add", "a,acc");
5902 if (sameRegs (AOP (left), AOP (result)) &&
5903 size >= MSB16 + offr && offr != LSB)
5904 emitcode ("xch", "a,%s",
5905 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5907 aopPut (AOP (result), "a", LSB + offr);
5910 if (size >= MSB16 + offr)
5912 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5914 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5917 emitcode ("rlc", "a");
5918 if (sameRegs (AOP (left), AOP (result)) &&
5919 size >= MSB24 + offr && offr != LSB)
5920 emitcode ("xch", "a,%s",
5921 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5923 aopPut (AOP (result), "a", MSB16 + offr);
5926 if (size >= MSB24 + offr)
5928 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5930 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5933 emitcode ("rlc", "a");
5934 if (sameRegs (AOP (left), AOP (result)) &&
5935 size >= MSB32 + offr && offr != LSB)
5936 emitcode ("xch", "a,%s",
5937 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5939 aopPut (AOP (result), "a", MSB24 + offr);
5942 if (size > MSB32 + offr)
5944 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5946 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5949 emitcode ("rlc", "a");
5950 aopPut (AOP (result), "a", MSB32 + offr);
5953 aopPut (AOP (result), zero, LSB);
5956 /*-----------------------------------------------------------------*/
5957 /* genlshFour - shift four byte by a known amount != 0 */
5958 /*-----------------------------------------------------------------*/
5960 genlshFour (operand * result, operand * left, int shCount)
5964 size = AOP_SIZE (result);
5966 /* if shifting more that 3 bytes */
5971 /* lowest order of left goes to the highest
5972 order of the destination */
5973 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5975 movLeft2Result (left, LSB, result, MSB32, 0);
5976 aopPut (AOP (result), zero, LSB);
5977 aopPut (AOP (result), zero, MSB16);
5978 aopPut (AOP (result), zero, MSB32);
5982 /* more than two bytes */
5983 else if (shCount >= 16)
5985 /* lower order two bytes goes to higher order two bytes */
5987 /* if some more remaining */
5989 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5992 movLeft2Result (left, MSB16, result, MSB32, 0);
5993 movLeft2Result (left, LSB, result, MSB24, 0);
5995 aopPut (AOP (result), zero, MSB16);
5996 aopPut (AOP (result), zero, LSB);
6000 /* if more than 1 byte */
6001 else if (shCount >= 8)
6003 /* lower order three bytes goes to higher order three bytes */
6008 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6010 movLeft2Result (left, LSB, result, MSB16, 0);
6016 movLeft2Result (left, MSB24, result, MSB32, 0);
6017 movLeft2Result (left, MSB16, result, MSB24, 0);
6018 movLeft2Result (left, LSB, result, MSB16, 0);
6019 aopPut (AOP (result), zero, LSB);
6021 else if (shCount == 1)
6022 shiftLLong (left, result, MSB16);
6025 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6026 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6027 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6028 aopPut (AOP (result), zero, LSB);
6033 /* 1 <= shCount <= 7 */
6034 else if (shCount <= 2)
6036 shiftLLong (left, result, LSB);
6038 shiftLLong (result, result, LSB);
6040 /* 3 <= shCount <= 7, optimize */
6043 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6044 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6045 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6049 /*-----------------------------------------------------------------*/
6050 /* genLeftShiftLiteral - left shifting by known count */
6051 /*-----------------------------------------------------------------*/
6053 genLeftShiftLiteral (operand * left,
6058 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6061 freeAsmop (right, NULL, ic, TRUE);
6063 aopOp (left, ic, FALSE);
6064 aopOp (result, ic, FALSE);
6066 size = getSize (operandType (result));
6069 emitcode ("; shift left ", "result %d, left %d", size,
6073 /* I suppose that the left size >= result size */
6078 movLeft2Result (left, size, result, size, 0);
6082 else if (shCount >= (size * 8))
6084 aopPut (AOP (result), zero, size);
6090 genlshOne (result, left, shCount);
6095 genlshTwo (result, left, shCount);
6099 genlshFour (result, left, shCount);
6103 freeAsmop (left, NULL, ic, TRUE);
6104 freeAsmop (result, NULL, ic, TRUE);
6107 /*-----------------------------------------------------------------*/
6108 /* genLeftShift - generates code for left shifting */
6109 /*-----------------------------------------------------------------*/
6111 genLeftShift (iCode * ic)
6113 operand *left, *right, *result;
6116 symbol *tlbl, *tlbl1;
6118 right = IC_RIGHT (ic);
6119 left = IC_LEFT (ic);
6120 result = IC_RESULT (ic);
6122 aopOp (right, ic, FALSE);
6124 /* if the shift count is known then do it
6125 as efficiently as possible */
6126 if (AOP_TYPE (right) == AOP_LIT)
6128 genLeftShiftLiteral (left, right, result, ic);
6132 /* shift count is unknown then we have to form
6133 a loop get the loop count in B : Note: we take
6134 only the lower order byte since shifting
6135 more that 32 bits make no sense anyway, ( the
6136 largest size of an object can be only 32 bits ) */
6138 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6139 emitcode ("inc", "b");
6140 freeAsmop (right, NULL, ic, TRUE);
6141 aopOp (left, ic, FALSE);
6142 aopOp (result, ic, FALSE);
6144 /* now move the left to the result if they are not the
6146 if (!sameRegs (AOP (left), AOP (result)) &&
6147 AOP_SIZE (result) > 1)
6150 size = AOP_SIZE (result);
6154 l = aopGet (AOP (left), offset, FALSE, TRUE);
6155 if (*l == '@' && (IS_AOP_PREG (result)))
6158 emitcode ("mov", "a,%s", l);
6159 aopPut (AOP (result), "a", offset);
6162 aopPut (AOP (result), l, offset);
6167 tlbl = newiTempLabel (NULL);
6168 size = AOP_SIZE (result);
6170 tlbl1 = newiTempLabel (NULL);
6172 /* if it is only one byte then */
6175 symbol *tlbl1 = newiTempLabel (NULL);
6177 l = aopGet (AOP (left), 0, FALSE, FALSE);
6179 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6180 emitcode ("", "%05d$:", tlbl->key + 100);
6181 emitcode ("add", "a,acc");
6182 emitcode ("", "%05d$:", tlbl1->key + 100);
6183 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6184 aopPut (AOP (result), "a", 0);
6188 reAdjustPreg (AOP (result));
6190 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6191 emitcode ("", "%05d$:", tlbl->key + 100);
6192 l = aopGet (AOP (result), offset, FALSE, FALSE);
6194 emitcode ("add", "a,acc");
6195 aopPut (AOP (result), "a", offset++);
6198 l = aopGet (AOP (result), offset, FALSE, FALSE);
6200 emitcode ("rlc", "a");
6201 aopPut (AOP (result), "a", offset++);
6203 reAdjustPreg (AOP (result));
6205 emitcode ("", "%05d$:", tlbl1->key + 100);
6206 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6208 freeAsmop (left, NULL, ic, TRUE);
6209 freeAsmop (result, NULL, ic, TRUE);
6212 /*-----------------------------------------------------------------*/
6213 /* genrshOne - right shift a one byte quantity by known count */
6214 /*-----------------------------------------------------------------*/
6216 genrshOne (operand * result, operand * left,
6217 int shCount, int sign)
6219 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6222 /*-----------------------------------------------------------------*/
6223 /* genrshTwo - right shift two bytes by known amount != 0 */
6224 /*-----------------------------------------------------------------*/
6226 genrshTwo (operand * result, operand * left,
6227 int shCount, int sign)
6229 /* if shCount >= 8 */
6234 shiftR1Left2Result (left, MSB16, result, LSB,
6237 movLeft2Result (left, MSB16, result, LSB, sign);
6238 addSign (result, MSB16, sign);
6241 /* 1 <= shCount <= 7 */
6243 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6246 /*-----------------------------------------------------------------*/
6247 /* shiftRLong - shift right one long from left to result */
6248 /* offl = LSB or MSB16 */
6249 /*-----------------------------------------------------------------*/
6251 shiftRLong (operand * left, int offl,
6252 operand * result, int sign)
6255 emitcode ("clr", "c");
6256 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6258 emitcode ("mov", "c,acc.7");
6259 emitcode ("rrc", "a");
6260 aopPut (AOP (result), "a", MSB32 - offl);
6262 /* add sign of "a" */
6263 addSign (result, MSB32, sign);
6265 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6266 emitcode ("rrc", "a");
6267 aopPut (AOP (result), "a", MSB24 - offl);
6269 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6270 emitcode ("rrc", "a");
6271 aopPut (AOP (result), "a", MSB16 - offl);
6275 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6276 emitcode ("rrc", "a");
6277 aopPut (AOP (result), "a", LSB);
6281 /*-----------------------------------------------------------------*/
6282 /* genrshFour - shift four byte by a known amount != 0 */
6283 /*-----------------------------------------------------------------*/
6285 genrshFour (operand * result, operand * left,
6286 int shCount, int sign)
6288 /* if shifting more that 3 bytes */
6293 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6295 movLeft2Result (left, MSB32, result, LSB, sign);
6296 addSign (result, MSB16, sign);
6298 else if (shCount >= 16)
6302 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6305 movLeft2Result (left, MSB24, result, LSB, 0);
6306 movLeft2Result (left, MSB32, result, MSB16, sign);
6308 addSign (result, MSB24, sign);
6310 else if (shCount >= 8)
6314 shiftRLong (left, MSB16, result, sign);
6315 else if (shCount == 0)
6317 movLeft2Result (left, MSB16, result, LSB, 0);
6318 movLeft2Result (left, MSB24, result, MSB16, 0);
6319 movLeft2Result (left, MSB32, result, MSB24, sign);
6320 addSign (result, MSB32, sign);
6324 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6325 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6326 /* the last shift is signed */
6327 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6328 addSign (result, MSB32, sign);
6332 { /* 1 <= shCount <= 7 */
6335 shiftRLong (left, LSB, result, sign);
6337 shiftRLong (result, LSB, result, sign);
6341 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6342 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6343 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6348 /*-----------------------------------------------------------------*/
6349 /* genRightShiftLiteral - right shifting by known count */
6350 /*-----------------------------------------------------------------*/
6352 genRightShiftLiteral (operand * left,
6358 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6361 freeAsmop (right, NULL, ic, TRUE);
6363 aopOp (left, ic, FALSE);
6364 aopOp (result, ic, FALSE);
6367 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6371 size = getDataSize (left);
6372 /* test the LEFT size !!! */
6374 /* I suppose that the left size >= result size */
6377 size = getDataSize (result);
6379 movLeft2Result (left, size, result, size, 0);
6382 else if (shCount >= (size * 8))
6385 /* get sign in acc.7 */
6386 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6387 addSign (result, LSB, sign);
6394 genrshOne (result, left, shCount, sign);
6398 genrshTwo (result, left, shCount, sign);
6402 genrshFour (result, left, shCount, sign);
6408 freeAsmop (left, NULL, ic, TRUE);
6409 freeAsmop (result, NULL, ic, TRUE);
6413 /*-----------------------------------------------------------------*/
6414 /* genSignedRightShift - right shift of signed number */
6415 /*-----------------------------------------------------------------*/
6417 genSignedRightShift (iCode * ic)
6419 operand *right, *left, *result;
6422 symbol *tlbl, *tlbl1;
6424 /* we do it the hard way put the shift count in b
6425 and loop thru preserving the sign */
6427 right = IC_RIGHT (ic);
6428 left = IC_LEFT (ic);
6429 result = IC_RESULT (ic);
6431 aopOp (right, ic, FALSE);
6434 if (AOP_TYPE (right) == AOP_LIT)
6436 genRightShiftLiteral (left, right, result, ic, 1);
6439 /* shift count is unknown then we have to form
6440 a loop get the loop count in B : Note: we take
6441 only the lower order byte since shifting
6442 more that 32 bits make no sense anyway, ( the
6443 largest size of an object can be only 32 bits ) */
6445 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6446 emitcode ("inc", "b");
6447 freeAsmop (right, NULL, ic, TRUE);
6448 aopOp (left, ic, FALSE);
6449 aopOp (result, ic, FALSE);
6451 /* now move the left to the result if they are not the
6453 if (!sameRegs (AOP (left), AOP (result)) &&
6454 AOP_SIZE (result) > 1)
6457 size = AOP_SIZE (result);
6461 l = aopGet (AOP (left), offset, FALSE, TRUE);
6462 if (*l == '@' && IS_AOP_PREG (result))
6465 emitcode ("mov", "a,%s", l);
6466 aopPut (AOP (result), "a", offset);
6469 aopPut (AOP (result), l, offset);
6474 /* mov the highest order bit to OVR */
6475 tlbl = newiTempLabel (NULL);
6476 tlbl1 = newiTempLabel (NULL);
6478 size = AOP_SIZE (result);
6480 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6481 emitcode ("rlc", "a");
6482 emitcode ("mov", "ov,c");
6483 /* if it is only one byte then */
6486 l = aopGet (AOP (left), 0, FALSE, FALSE);
6488 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6489 emitcode ("", "%05d$:", tlbl->key + 100);
6490 emitcode ("mov", "c,ov");
6491 emitcode ("rrc", "a");
6492 emitcode ("", "%05d$:", tlbl1->key + 100);
6493 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6494 aopPut (AOP (result), "a", 0);
6498 reAdjustPreg (AOP (result));
6499 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6500 emitcode ("", "%05d$:", tlbl->key + 100);
6501 emitcode ("mov", "c,ov");
6504 l = aopGet (AOP (result), offset, FALSE, FALSE);
6506 emitcode ("rrc", "a");
6507 aopPut (AOP (result), "a", offset--);
6509 reAdjustPreg (AOP (result));
6510 emitcode ("", "%05d$:", tlbl1->key + 100);
6511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6514 freeAsmop (left, NULL, ic, TRUE);
6515 freeAsmop (result, NULL, ic, TRUE);
6518 /*-----------------------------------------------------------------*/
6519 /* genRightShift - generate code for right shifting */
6520 /*-----------------------------------------------------------------*/
6522 genRightShift (iCode * ic)
6524 operand *right, *left, *result;
6528 symbol *tlbl, *tlbl1;
6530 /* if signed then we do it the hard way preserve the
6531 sign bit moving it inwards */
6532 retype = getSpec (operandType (IC_RESULT (ic)));
6534 if (!SPEC_USIGN (retype))
6536 genSignedRightShift (ic);
6540 /* signed & unsigned types are treated the same : i.e. the
6541 signed is NOT propagated inwards : quoting from the
6542 ANSI - standard : "for E1 >> E2, is equivalent to division
6543 by 2**E2 if unsigned or if it has a non-negative value,
6544 otherwise the result is implementation defined ", MY definition
6545 is that the sign does not get propagated */
6547 right = IC_RIGHT (ic);
6548 left = IC_LEFT (ic);
6549 result = IC_RESULT (ic);
6551 aopOp (right, ic, FALSE);
6553 /* if the shift count is known then do it
6554 as efficiently as possible */
6555 if (AOP_TYPE (right) == AOP_LIT)
6557 genRightShiftLiteral (left, right, result, ic, 0);
6561 /* shift count is unknown then we have to form
6562 a loop get the loop count in B : Note: we take
6563 only the lower order byte since shifting
6564 more that 32 bits make no sense anyway, ( the
6565 largest size of an object can be only 32 bits ) */
6567 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6568 emitcode ("inc", "b");
6569 freeAsmop (right, NULL, ic, TRUE);
6570 aopOp (left, ic, FALSE);
6571 aopOp (result, ic, FALSE);
6573 /* now move the left to the result if they are not the
6575 if (!sameRegs (AOP (left), AOP (result)) &&
6576 AOP_SIZE (result) > 1)
6579 size = AOP_SIZE (result);
6583 l = aopGet (AOP (left), offset, FALSE, TRUE);
6584 if (*l == '@' && IS_AOP_PREG (result))
6587 emitcode ("mov", "a,%s", l);
6588 aopPut (AOP (result), "a", offset);
6591 aopPut (AOP (result), l, offset);
6596 tlbl = newiTempLabel (NULL);
6597 tlbl1 = newiTempLabel (NULL);
6598 size = AOP_SIZE (result);
6601 /* if it is only one byte then */
6604 l = aopGet (AOP (left), 0, FALSE, FALSE);
6606 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6607 emitcode ("", "%05d$:", tlbl->key + 100);
6609 emitcode ("rrc", "a");
6610 emitcode ("", "%05d$:", tlbl1->key + 100);
6611 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6612 aopPut (AOP (result), "a", 0);
6616 reAdjustPreg (AOP (result));
6617 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6618 emitcode ("", "%05d$:", tlbl->key + 100);
6622 l = aopGet (AOP (result), offset, FALSE, FALSE);
6624 emitcode ("rrc", "a");
6625 aopPut (AOP (result), "a", offset--);
6627 reAdjustPreg (AOP (result));
6629 emitcode ("", "%05d$:", tlbl1->key + 100);
6630 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6633 freeAsmop (left, NULL, ic, TRUE);
6634 freeAsmop (result, NULL, ic, TRUE);
6637 /*-----------------------------------------------------------------*/
6638 /* genUnpackBits - generates code for unpacking bits */
6639 /*-----------------------------------------------------------------*/
6641 genUnpackBits (operand * result, char *rname, int ptype)
6649 etype = getSpec (operandType (result));
6650 rsize = getSize (operandType (result));
6651 /* read the first byte */
6657 emitcode ("mov", "a,@%s", rname);
6661 emitcode ("movx", "a,@%s", rname);
6665 emitcode ("movx", "a,@dptr");
6669 emitcode ("clr", "a");
6670 emitcode ("movc", "a,%s", "@a+dptr");
6674 emitcode ("lcall", "__gptrget");
6678 rlen = SPEC_BLEN (etype);
6680 /* if we have bitdisplacement then it fits */
6681 /* into this byte completely or if length is */
6682 /* less than a byte */
6683 if ((shCnt = SPEC_BSTR (etype)) ||
6684 (SPEC_BLEN (etype) <= 8))
6687 /* shift right acc */
6690 emitcode ("anl", "a,#0x%02x",
6691 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6692 aopPut (AOP (result), "a", offset++);
6696 /* bit field did not fit in a byte */
6697 aopPut (AOP (result), "a", offset++);
6706 emitcode ("inc", "%s", rname);
6707 emitcode ("mov", "a,@%s", rname);
6711 emitcode ("inc", "%s", rname);
6712 emitcode ("movx", "a,@%s", rname);
6716 emitcode ("inc", "dptr");
6717 emitcode ("movx", "a,@dptr");
6721 emitcode ("clr", "a");
6722 emitcode ("inc", "dptr");
6723 emitcode ("movc", "a", "@a+dptr");
6727 emitcode ("inc", "dptr");
6728 emitcode ("lcall", "__gptrget");
6733 /* if we are done */
6737 aopPut (AOP (result), "a", offset++);
6743 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6745 aopPut (AOP (result), "a", offset++);
6753 aopPut (AOP (result), zero, offset++);
6759 /*-----------------------------------------------------------------*/
6760 /* genDataPointerGet - generates code when ptr offset is known */
6761 /*-----------------------------------------------------------------*/
6763 genDataPointerGet (operand * left,
6769 int size, offset = 0;
6770 aopOp (result, ic, TRUE);
6772 /* get the string representation of the name */
6773 l = aopGet (AOP (left), 0, FALSE, TRUE);
6774 size = AOP_SIZE (result);
6778 sprintf (buffer, "(%s + %d)", l + 1, offset);
6780 sprintf (buffer, "%s", l + 1);
6781 aopPut (AOP (result), buffer, offset++);
6784 freeAsmop (left, NULL, ic, TRUE);
6785 freeAsmop (result, NULL, ic, TRUE);
6788 /*-----------------------------------------------------------------*/
6789 /* genNearPointerGet - emitcode for near pointer fetch */
6790 /*-----------------------------------------------------------------*/
6792 genNearPointerGet (operand * left,
6799 sym_link *rtype, *retype;
6800 sym_link *ltype = operandType (left);
6803 rtype = operandType (result);
6804 retype = getSpec (rtype);
6806 aopOp (left, ic, FALSE);
6808 /* if left is rematerialisable and
6809 result is not bit variable type and
6810 the left is pointer to data space i.e
6811 lower 128 bytes of space */
6812 if (AOP_TYPE (left) == AOP_IMMD &&
6813 !IS_BITVAR (retype) &&
6814 DCL_TYPE (ltype) == POINTER)
6816 genDataPointerGet (left, result, ic);
6820 /* if the value is already in a pointer register
6821 then don't need anything more */
6822 if (!AOP_INPREG (AOP (left)))
6824 /* otherwise get a free pointer register */
6826 preg = getFreePtr (ic, &aop, FALSE);
6827 emitcode ("mov", "%s,%s",
6829 aopGet (AOP (left), 0, FALSE, TRUE));
6833 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6835 freeAsmop (left, NULL, ic, TRUE);
6836 aopOp (result, ic, FALSE);
6838 /* if bitfield then unpack the bits */
6839 if (IS_BITVAR (retype))
6840 genUnpackBits (result, rname, POINTER);
6843 /* we have can just get the values */
6844 int size = AOP_SIZE (result);
6849 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6852 emitcode ("mov", "a,@%s", rname);
6853 aopPut (AOP (result), "a", offset);
6857 sprintf (buffer, "@%s", rname);
6858 aopPut (AOP (result), buffer, offset);
6862 emitcode ("inc", "%s", rname);
6866 /* now some housekeeping stuff */
6869 /* we had to allocate for this iCode */
6870 freeAsmop (NULL, aop, ic, TRUE);
6874 /* we did not allocate which means left
6875 already in a pointer register, then
6876 if size > 0 && this could be used again
6877 we have to point it back to where it
6879 if (AOP_SIZE (result) > 1 &&
6880 !OP_SYMBOL (left)->remat &&
6881 (OP_SYMBOL (left)->liveTo > ic->seq ||
6884 int size = AOP_SIZE (result) - 1;
6886 emitcode ("dec", "%s", rname);
6891 freeAsmop (result, NULL, ic, TRUE);
6895 /*-----------------------------------------------------------------*/
6896 /* genPagedPointerGet - emitcode for paged pointer fetch */
6897 /*-----------------------------------------------------------------*/
6899 genPagedPointerGet (operand * left,
6906 sym_link *rtype, *retype;
6908 rtype = operandType (result);
6909 retype = getSpec (rtype);
6911 aopOp (left, ic, FALSE);
6913 /* if the value is already in a pointer register
6914 then don't need anything more */
6915 if (!AOP_INPREG (AOP (left)))
6917 /* otherwise get a free pointer register */
6919 preg = getFreePtr (ic, &aop, FALSE);
6920 emitcode ("mov", "%s,%s",
6922 aopGet (AOP (left), 0, FALSE, TRUE));
6926 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6928 freeAsmop (left, NULL, ic, TRUE);
6929 aopOp (result, ic, FALSE);
6931 /* if bitfield then unpack the bits */
6932 if (IS_BITVAR (retype))
6933 genUnpackBits (result, rname, PPOINTER);
6936 /* we have can just get the values */
6937 int size = AOP_SIZE (result);
6943 emitcode ("movx", "a,@%s", rname);
6944 aopPut (AOP (result), "a", offset);
6949 emitcode ("inc", "%s", rname);
6953 /* now some housekeeping stuff */
6956 /* we had to allocate for this iCode */
6957 freeAsmop (NULL, aop, ic, TRUE);
6961 /* we did not allocate which means left
6962 already in a pointer register, then
6963 if size > 0 && this could be used again
6964 we have to point it back to where it
6966 if (AOP_SIZE (result) > 1 &&
6967 !OP_SYMBOL (left)->remat &&
6968 (OP_SYMBOL (left)->liveTo > ic->seq ||
6971 int size = AOP_SIZE (result) - 1;
6973 emitcode ("dec", "%s", rname);
6978 freeAsmop (result, NULL, ic, TRUE);
6983 /*-----------------------------------------------------------------*/
6984 /* genFarPointerGet - gget value from far space */
6985 /*-----------------------------------------------------------------*/
6987 genFarPointerGet (operand * left,
6988 operand * result, iCode * ic)
6991 sym_link *retype = getSpec (operandType (result));
6993 aopOp (left, ic, FALSE);
6995 /* if the operand is already in dptr
6996 then we do nothing else we move the value to dptr */
6997 if (AOP_TYPE (left) != AOP_STR)
6999 /* if this is remateriazable */
7000 if (AOP_TYPE (left) == AOP_IMMD)
7001 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7003 { /* we need to get it byte by byte */
7004 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7005 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7008 /* so dptr know contains the address */
7009 freeAsmop (left, NULL, ic, TRUE);
7010 aopOp (result, ic, FALSE);
7012 /* if bit then unpack */
7013 if (IS_BITVAR (retype))
7014 genUnpackBits (result, "dptr", FPOINTER);
7017 size = AOP_SIZE (result);
7022 emitcode ("movx", "a,@dptr");
7023 aopPut (AOP (result), "a", offset++);
7025 emitcode ("inc", "dptr");
7029 freeAsmop (result, NULL, ic, TRUE);
7032 /*-----------------------------------------------------------------*/
7033 /* emitcodePointerGet - gget value from code space */
7034 /*-----------------------------------------------------------------*/
7036 emitcodePointerGet (operand * left,
7037 operand * result, iCode * ic)
7040 sym_link *retype = getSpec (operandType (result));
7042 aopOp (left, ic, FALSE);
7044 /* if the operand is already in dptr
7045 then we do nothing else we move the value to dptr */
7046 if (AOP_TYPE (left) != AOP_STR)
7048 /* if this is remateriazable */
7049 if (AOP_TYPE (left) == AOP_IMMD)
7050 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7052 { /* we need to get it byte by byte */
7053 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7054 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7057 /* so dptr know contains the address */
7058 freeAsmop (left, NULL, ic, TRUE);
7059 aopOp (result, ic, FALSE);
7061 /* if bit then unpack */
7062 if (IS_BITVAR (retype))
7063 genUnpackBits (result, "dptr", CPOINTER);
7066 size = AOP_SIZE (result);
7071 emitcode ("clr", "a");
7072 emitcode ("movc", "a,@a+dptr");
7073 aopPut (AOP (result), "a", offset++);
7075 emitcode ("inc", "dptr");
7079 freeAsmop (result, NULL, ic, TRUE);
7082 /*-----------------------------------------------------------------*/
7083 /* genGenPointerGet - gget value from generic pointer space */
7084 /*-----------------------------------------------------------------*/
7086 genGenPointerGet (operand * left,
7087 operand * result, iCode * ic)
7090 sym_link *retype = getSpec (operandType (result));
7092 aopOp (left, ic, FALSE);
7094 /* if the operand is already in dptr
7095 then we do nothing else we move the value to dptr */
7096 if (AOP_TYPE (left) != AOP_STR)
7098 /* if this is remateriazable */
7099 if (AOP_TYPE (left) == AOP_IMMD)
7101 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7102 emitcode ("mov", "b,#%d", pointerCode (retype));
7105 { /* we need to get it byte by byte */
7106 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7107 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7108 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7111 /* so dptr know contains the address */
7112 freeAsmop (left, NULL, ic, TRUE);
7113 aopOp (result, ic, FALSE);
7115 /* if bit then unpack */
7116 if (IS_BITVAR (retype))
7117 genUnpackBits (result, "dptr", GPOINTER);
7120 size = AOP_SIZE (result);
7125 emitcode ("lcall", "__gptrget");
7126 aopPut (AOP (result), "a", offset++);
7128 emitcode ("inc", "dptr");
7132 freeAsmop (result, NULL, ic, TRUE);
7135 /*-----------------------------------------------------------------*/
7136 /* genPointerGet - generate code for pointer get */
7137 /*-----------------------------------------------------------------*/
7139 genPointerGet (iCode * ic)
7141 operand *left, *result;
7142 sym_link *type, *etype;
7145 left = IC_LEFT (ic);
7146 result = IC_RESULT (ic);
7148 /* depending on the type of pointer we need to
7149 move it to the correct pointer register */
7150 type = operandType (left);
7151 etype = getSpec (type);
7152 /* if left is of type of pointer then it is simple */
7153 if (IS_PTR (type) && !IS_FUNC (type->next))
7154 p_type = DCL_TYPE (type);
7157 /* we have to go by the storage class */
7158 p_type = PTR_TYPE (SPEC_OCLS (etype));
7160 /* if (SPEC_OCLS(etype)->codesp ) { */
7161 /* p_type = CPOINTER ; */
7164 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7165 /* p_type = FPOINTER ; */
7167 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7168 /* p_type = PPOINTER; */
7170 /* if (SPEC_OCLS(etype) == idata ) */
7171 /* p_type = IPOINTER; */
7173 /* p_type = POINTER ; */
7176 /* now that we have the pointer type we assign
7177 the pointer values */
7183 genNearPointerGet (left, result, ic);
7187 genPagedPointerGet (left, result, ic);
7191 genFarPointerGet (left, result, ic);
7195 emitcodePointerGet (left, result, ic);
7199 genGenPointerGet (left, result, ic);
7205 /*-----------------------------------------------------------------*/
7206 /* genPackBits - generates code for packed bit storage */
7207 /*-----------------------------------------------------------------*/
7209 genPackBits (sym_link * etype,
7211 char *rname, int p_type)
7219 blen = SPEC_BLEN (etype);
7220 bstr = SPEC_BSTR (etype);
7222 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7225 /* if the bit lenth is less than or */
7226 /* it exactly fits a byte then */
7227 if (SPEC_BLEN (etype) <= 8)
7229 shCount = SPEC_BSTR (etype);
7231 /* shift left acc */
7234 if (SPEC_BLEN (etype) < 8)
7235 { /* if smaller than a byte */
7241 emitcode ("mov", "b,a");
7242 emitcode ("mov", "a,@%s", rname);
7246 emitcode ("mov", "b,a");
7247 emitcode ("movx", "a,@dptr");
7251 emitcode ("push", "b");
7252 emitcode ("push", "acc");
7253 emitcode ("lcall", "__gptrget");
7254 emitcode ("pop", "b");
7258 emitcode ("anl", "a,#0x%02x", (unsigned char)
7259 ((unsigned char) (0xFF << (blen + bstr)) |
7260 (unsigned char) (0xFF >> (8 - bstr))));
7261 emitcode ("orl", "a,b");
7262 if (p_type == GPOINTER)
7263 emitcode ("pop", "b");
7270 emitcode ("mov", "@%s,a", rname);
7274 emitcode ("movx", "@dptr,a");
7278 emitcode ("lcall", "__gptrput");
7283 if (SPEC_BLEN (etype) <= 8)
7286 emitcode ("inc", "%s", rname);
7287 rLen = SPEC_BLEN (etype);
7289 /* now generate for lengths greater than one byte */
7293 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7305 emitcode ("mov", "@%s,a", rname);
7308 emitcode ("mov", "@%s,%s", rname, l);
7313 emitcode ("movx", "@dptr,a");
7318 emitcode ("lcall", "__gptrput");
7321 emitcode ("inc", "%s", rname);
7326 /* last last was not complete */
7329 /* save the byte & read byte */
7333 emitcode ("mov", "b,a");
7334 emitcode ("mov", "a,@%s", rname);
7338 emitcode ("mov", "b,a");
7339 emitcode ("movx", "a,@dptr");
7343 emitcode ("push", "b");
7344 emitcode ("push", "acc");
7345 emitcode ("lcall", "__gptrget");
7346 emitcode ("pop", "b");
7350 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7351 emitcode ("orl", "a,b");
7354 if (p_type == GPOINTER)
7355 emitcode ("pop", "b");
7361 emitcode ("mov", "@%s,a", rname);
7365 emitcode ("movx", "@dptr,a");
7369 emitcode ("lcall", "__gptrput");
7373 /*-----------------------------------------------------------------*/
7374 /* genDataPointerSet - remat pointer to data space */
7375 /*-----------------------------------------------------------------*/
7377 genDataPointerSet (operand * right,
7381 int size, offset = 0;
7382 char *l, buffer[256];
7384 aopOp (right, ic, FALSE);
7386 l = aopGet (AOP (result), 0, FALSE, TRUE);
7387 size = AOP_SIZE (right);
7391 sprintf (buffer, "(%s + %d)", l + 1, offset);
7393 sprintf (buffer, "%s", l + 1);
7394 emitcode ("mov", "%s,%s", buffer,
7395 aopGet (AOP (right), offset++, FALSE, FALSE));
7398 freeAsmop (right, NULL, ic, TRUE);
7399 freeAsmop (result, NULL, ic, TRUE);
7402 /*-----------------------------------------------------------------*/
7403 /* genNearPointerSet - emitcode for near pointer put */
7404 /*-----------------------------------------------------------------*/
7406 genNearPointerSet (operand * right,
7413 sym_link *retype, *letype;
7414 sym_link *ptype = operandType (result);
7416 retype = getSpec (operandType (right));
7417 letype = getSpec (ptype);
7418 aopOp (result, ic, FALSE);
7420 /* if the result is rematerializable &
7421 in data space & not a bit variable */
7422 if (AOP_TYPE (result) == AOP_IMMD &&
7423 DCL_TYPE (ptype) == POINTER &&
7424 !IS_BITVAR (retype) &&
7425 !IS_BITVAR (letype))
7427 genDataPointerSet (right, result, ic);
7431 /* if the value is already in a pointer register
7432 then don't need anything more */
7433 if (!AOP_INPREG (AOP (result)))
7435 /* otherwise get a free pointer register */
7437 preg = getFreePtr (ic, &aop, FALSE);
7438 emitcode ("mov", "%s,%s",
7440 aopGet (AOP (result), 0, FALSE, TRUE));
7444 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7446 freeAsmop (result, NULL, ic, TRUE);
7447 aopOp (right, ic, FALSE);
7449 /* if bitfield then unpack the bits */
7450 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7451 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7454 /* we have can just get the values */
7455 int size = AOP_SIZE (right);
7460 l = aopGet (AOP (right), offset, FALSE, TRUE);
7464 emitcode ("mov", "@%s,a", rname);
7467 emitcode ("mov", "@%s,%s", rname, l);
7469 emitcode ("inc", "%s", rname);
7474 /* now some housekeeping stuff */
7477 /* we had to allocate for this iCode */
7478 freeAsmop (NULL, aop, ic, TRUE);
7482 /* we did not allocate which means left
7483 already in a pointer register, then
7484 if size > 0 && this could be used again
7485 we have to point it back to where it
7487 if (AOP_SIZE (right) > 1 &&
7488 !OP_SYMBOL (result)->remat &&
7489 (OP_SYMBOL (result)->liveTo > ic->seq ||
7492 int size = AOP_SIZE (right) - 1;
7494 emitcode ("dec", "%s", rname);
7499 freeAsmop (right, NULL, ic, TRUE);
7504 /*-----------------------------------------------------------------*/
7505 /* genPagedPointerSet - emitcode for Paged pointer put */
7506 /*-----------------------------------------------------------------*/
7508 genPagedPointerSet (operand * right,
7515 sym_link *retype, *letype;
7517 retype = getSpec (operandType (right));
7518 letype = getSpec (operandType (result));
7520 aopOp (result, ic, FALSE);
7522 /* if the value is already in a pointer register
7523 then don't need anything more */
7524 if (!AOP_INPREG (AOP (result)))
7526 /* otherwise get a free pointer register */
7528 preg = getFreePtr (ic, &aop, FALSE);
7529 emitcode ("mov", "%s,%s",
7531 aopGet (AOP (result), 0, FALSE, TRUE));
7535 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7537 freeAsmop (result, NULL, ic, TRUE);
7538 aopOp (right, ic, FALSE);
7540 /* if bitfield then unpack the bits */
7541 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7542 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7545 /* we have can just get the values */
7546 int size = AOP_SIZE (right);
7551 l = aopGet (AOP (right), offset, FALSE, TRUE);
7554 emitcode ("movx", "@%s,a", rname);
7557 emitcode ("inc", "%s", rname);
7563 /* now some housekeeping stuff */
7566 /* we had to allocate for this iCode */
7567 freeAsmop (NULL, aop, ic, TRUE);
7571 /* we did not allocate which means left
7572 already in a pointer register, then
7573 if size > 0 && this could be used again
7574 we have to point it back to where it
7576 if (AOP_SIZE (right) > 1 &&
7577 !OP_SYMBOL (result)->remat &&
7578 (OP_SYMBOL (result)->liveTo > ic->seq ||
7581 int size = AOP_SIZE (right) - 1;
7583 emitcode ("dec", "%s", rname);
7588 freeAsmop (right, NULL, ic, TRUE);
7593 /*-----------------------------------------------------------------*/
7594 /* genFarPointerSet - set value from far space */
7595 /*-----------------------------------------------------------------*/
7597 genFarPointerSet (operand * right,
7598 operand * result, iCode * ic)
7601 sym_link *retype = getSpec (operandType (right));
7602 sym_link *letype = getSpec (operandType (result));
7603 aopOp (result, ic, FALSE);
7605 /* if the operand is already in dptr
7606 then we do nothing else we move the value to dptr */
7607 if (AOP_TYPE (result) != AOP_STR)
7609 /* if this is remateriazable */
7610 if (AOP_TYPE (result) == AOP_IMMD)
7611 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7613 { /* we need to get it byte by byte */
7614 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7615 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7618 /* so dptr know contains the address */
7619 freeAsmop (result, NULL, ic, TRUE);
7620 aopOp (right, ic, FALSE);
7622 /* if bit then unpack */
7623 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7624 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7627 size = AOP_SIZE (right);
7632 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7634 emitcode ("movx", "@dptr,a");
7636 emitcode ("inc", "dptr");
7640 freeAsmop (right, NULL, ic, TRUE);
7643 /*-----------------------------------------------------------------*/
7644 /* genGenPointerSet - set value from generic pointer space */
7645 /*-----------------------------------------------------------------*/
7647 genGenPointerSet (operand * right,
7648 operand * result, iCode * ic)
7651 sym_link *retype = getSpec (operandType (right));
7652 sym_link *letype = getSpec (operandType (result));
7654 aopOp (result, ic, FALSE);
7656 /* if the operand is already in dptr
7657 then we do nothing else we move the value to dptr */
7658 if (AOP_TYPE (result) != AOP_STR)
7660 /* if this is remateriazable */
7661 if (AOP_TYPE (result) == AOP_IMMD)
7663 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7664 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7667 { /* we need to get it byte by byte */
7668 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7669 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7670 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7673 /* so dptr know contains the address */
7674 freeAsmop (result, NULL, ic, TRUE);
7675 aopOp (right, ic, FALSE);
7677 /* if bit then unpack */
7678 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7679 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7682 size = AOP_SIZE (right);
7687 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7689 emitcode ("lcall", "__gptrput");
7691 emitcode ("inc", "dptr");
7695 freeAsmop (right, NULL, ic, TRUE);
7698 /*-----------------------------------------------------------------*/
7699 /* genPointerSet - stores the value into a pointer location */
7700 /*-----------------------------------------------------------------*/
7702 genPointerSet (iCode * ic)
7704 operand *right, *result;
7705 sym_link *type, *etype;
7708 right = IC_RIGHT (ic);
7709 result = IC_RESULT (ic);
7711 /* depending on the type of pointer we need to
7712 move it to the correct pointer register */
7713 type = operandType (result);
7714 etype = getSpec (type);
7715 /* if left is of type of pointer then it is simple */
7716 if (IS_PTR (type) && !IS_FUNC (type->next))
7718 p_type = DCL_TYPE (type);
7722 /* we have to go by the storage class */
7723 p_type = PTR_TYPE (SPEC_OCLS (etype));
7726 /* now that we have the pointer type we assign
7727 the pointer values */
7733 genNearPointerSet (right, result, ic);
7737 genPagedPointerSet (right, result, ic);
7741 genFarPointerSet (right, result, ic);
7745 genGenPointerSet (right, result, ic);
7751 /*-----------------------------------------------------------------*/
7752 /* genIfx - generate code for Ifx statement */
7753 /*-----------------------------------------------------------------*/
7755 genIfx (iCode * ic, iCode * popIc)
7757 operand *cond = IC_COND (ic);
7760 aopOp (cond, ic, FALSE);
7762 /* get the value into acc */
7763 if (AOP_TYPE (cond) != AOP_CRY)
7767 /* the result is now in the accumulator */
7768 freeAsmop (cond, NULL, ic, TRUE);
7770 /* if there was something to be popped then do it */
7774 /* if the condition is a bit variable */
7775 if (isbit && IS_ITEMP (cond) &&
7777 genIfxJump (ic, SPIL_LOC (cond)->rname);
7778 else if (isbit && !IS_ITEMP (cond))
7779 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7781 genIfxJump (ic, "a");
7786 /*-----------------------------------------------------------------*/
7787 /* genAddrOf - generates code for address of */
7788 /*-----------------------------------------------------------------*/
7790 genAddrOf (iCode * ic)
7792 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7795 aopOp (IC_RESULT (ic), ic, FALSE);
7797 /* if the operand is on the stack then we
7798 need to get the stack offset of this
7802 /* if it has an offset then we need to compute
7806 emitcode ("mov", "a,_bp");
7807 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7808 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7812 /* we can just move _bp */
7813 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7815 /* fill the result with zero */
7816 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7821 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7827 /* object not on stack then we need the name */
7828 size = AOP_SIZE (IC_RESULT (ic));
7833 char s[SDCC_NAME_MAX];
7835 sprintf (s, "#(%s >> %d)",
7839 sprintf (s, "#%s", sym->rname);
7840 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7848 /*-----------------------------------------------------------------*/
7849 /* genFarFarAssign - assignment when both are in far space */
7850 /*-----------------------------------------------------------------*/
7852 genFarFarAssign (operand * result, operand * right, iCode * ic)
7854 int size = AOP_SIZE (right);
7857 /* first push the right side on to the stack */
7860 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7862 emitcode ("push", "acc");
7865 freeAsmop (right, NULL, ic, FALSE);
7866 /* now assign DPTR to result */
7867 aopOp (result, ic, FALSE);
7868 size = AOP_SIZE (result);
7871 emitcode ("pop", "acc");
7872 aopPut (AOP (result), "a", --offset);
7874 freeAsmop (result, NULL, ic, FALSE);
7878 /*-----------------------------------------------------------------*/
7879 /* genAssign - generate code for assignment */
7880 /*-----------------------------------------------------------------*/
7882 genAssign (iCode * ic)
7884 operand *result, *right;
7886 unsigned long lit = 0L;
7888 result = IC_RESULT (ic);
7889 right = IC_RIGHT (ic);
7891 /* if they are the same */
7892 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7895 aopOp (right, ic, FALSE);
7897 /* special case both in far space */
7898 if ((AOP_TYPE (right) == AOP_DPTR ||
7899 AOP_TYPE (right) == AOP_DPTR2) &&
7900 IS_TRUE_SYMOP (result) &&
7901 isOperandInFarSpace (result))
7904 genFarFarAssign (result, right, ic);
7908 aopOp (result, ic, TRUE);
7910 /* if they are the same registers */
7911 if (sameRegs (AOP (right), AOP (result)))
7914 /* if the result is a bit */
7915 if (AOP_TYPE (result) == AOP_CRY)
7918 /* if the right size is a literal then
7919 we know what the value is */
7920 if (AOP_TYPE (right) == AOP_LIT)
7922 if (((int) operandLitValue (right)))
7923 aopPut (AOP (result), one, 0);
7925 aopPut (AOP (result), zero, 0);
7929 /* the right is also a bit variable */
7930 if (AOP_TYPE (right) == AOP_CRY)
7932 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7933 aopPut (AOP (result), "c", 0);
7939 aopPut (AOP (result), "a", 0);
7943 /* bit variables done */
7945 size = AOP_SIZE (result);
7947 if (AOP_TYPE (right) == AOP_LIT)
7948 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7950 (AOP_TYPE (result) != AOP_REG) &&
7951 (AOP_TYPE (right) == AOP_LIT) &&
7952 !IS_FLOAT (operandType (right)) &&
7955 emitcode ("clr", "a");
7958 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7959 aopPut (AOP (result), "a", size);
7961 aopPut (AOP (result),
7962 aopGet (AOP (right), size, FALSE, FALSE),
7970 aopPut (AOP (result),
7971 aopGet (AOP (right), offset, FALSE, FALSE),
7978 freeAsmop (right, NULL, ic, TRUE);
7979 freeAsmop (result, NULL, ic, TRUE);
7982 /*-----------------------------------------------------------------*/
7983 /* genJumpTab - genrates code for jump table */
7984 /*-----------------------------------------------------------------*/
7986 genJumpTab (iCode * ic)
7991 aopOp (IC_JTCOND (ic), ic, FALSE);
7992 /* get the condition into accumulator */
7993 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7995 /* multiply by three */
7996 emitcode ("add", "a,acc");
7997 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7998 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8000 jtab = newiTempLabel (NULL);
8001 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8002 emitcode ("jmp", "@a+dptr");
8003 emitcode ("", "%05d$:", jtab->key + 100);
8004 /* now generate the jump labels */
8005 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8006 jtab = setNextItem (IC_JTLABELS (ic)))
8007 emitcode ("ljmp", "%05d$", jtab->key + 100);
8011 /*-----------------------------------------------------------------*/
8012 /* genCast - gen code for casting */
8013 /*-----------------------------------------------------------------*/
8015 genCast (iCode * ic)
8017 operand *result = IC_RESULT (ic);
8018 sym_link *ctype = operandType (IC_LEFT (ic));
8019 sym_link *rtype = operandType (IC_RIGHT (ic));
8020 operand *right = IC_RIGHT (ic);
8023 /* if they are equivalent then do nothing */
8024 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8027 aopOp (right, ic, FALSE);
8028 aopOp (result, ic, FALSE);
8030 /* if the result is a bit */
8031 if (AOP_TYPE (result) == AOP_CRY)
8033 /* if the right size is a literal then
8034 we know what the value is */
8035 if (AOP_TYPE (right) == AOP_LIT)
8037 if (((int) operandLitValue (right)))
8038 aopPut (AOP (result), one, 0);
8040 aopPut (AOP (result), zero, 0);
8045 /* the right is also a bit variable */
8046 if (AOP_TYPE (right) == AOP_CRY)
8048 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8049 aopPut (AOP (result), "c", 0);
8055 aopPut (AOP (result), "a", 0);
8059 /* if they are the same size : or less */
8060 if (AOP_SIZE (result) <= AOP_SIZE (right))
8063 /* if they are in the same place */
8064 if (sameRegs (AOP (right), AOP (result)))
8067 /* if they in different places then copy */
8068 size = AOP_SIZE (result);
8072 aopPut (AOP (result),
8073 aopGet (AOP (right), offset, FALSE, FALSE),
8081 /* if the result is of type pointer */
8086 sym_link *type = operandType (right);
8087 sym_link *etype = getSpec (type);
8089 /* pointer to generic pointer */
8090 if (IS_GENPTR (ctype))
8095 p_type = DCL_TYPE (type);
8098 /* we have to go by the storage class */
8099 p_type = PTR_TYPE (SPEC_OCLS (etype));
8102 /* the first two bytes are known */
8103 size = GPTRSIZE - 1;
8107 aopPut (AOP (result),
8108 aopGet (AOP (right), offset, FALSE, FALSE),
8112 /* the last byte depending on type */
8130 /* this should never happen */
8131 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8132 "got unknown pointer type");
8135 aopPut (AOP (result), l, GPTRSIZE - 1);
8139 /* just copy the pointers */
8140 size = AOP_SIZE (result);
8144 aopPut (AOP (result),
8145 aopGet (AOP (right), offset, FALSE, FALSE),
8152 /* so we now know that the size of destination is greater
8153 than the size of the source */
8154 /* we move to result for the size of source */
8155 size = AOP_SIZE (right);
8159 aopPut (AOP (result),
8160 aopGet (AOP (right), offset, FALSE, FALSE),
8165 /* now depending on the sign of the source && destination */
8166 size = AOP_SIZE (result) - AOP_SIZE (right);
8167 /* if unsigned or not an integral type */
8168 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8171 aopPut (AOP (result), zero, offset++);
8175 /* we need to extend the sign :{ */
8176 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8179 emitcode ("rlc", "a");
8180 emitcode ("subb", "a,acc");
8182 aopPut (AOP (result), "a", offset++);
8185 /* we are done hurray !!!! */
8188 freeAsmop (right, NULL, ic, TRUE);
8189 freeAsmop (result, NULL, ic, TRUE);
8193 /*-----------------------------------------------------------------*/
8194 /* genDjnz - generate decrement & jump if not zero instrucion */
8195 /*-----------------------------------------------------------------*/
8197 genDjnz (iCode * ic, iCode * ifx)
8203 /* if the if condition has a false label
8204 then we cannot save */
8208 /* if the minus is not of the form
8210 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8211 !IS_OP_LITERAL (IC_RIGHT (ic)))
8214 if (operandLitValue (IC_RIGHT (ic)) != 1)
8217 /* if the size of this greater than one then no
8219 if (getSize (operandType (IC_RESULT (ic))) > 1)
8222 /* otherwise we can save BIG */
8223 lbl = newiTempLabel (NULL);
8224 lbl1 = newiTempLabel (NULL);
8226 aopOp (IC_RESULT (ic), ic, FALSE);
8228 if (IS_AOP_PREG (IC_RESULT (ic)))
8230 emitcode ("dec", "%s",
8231 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8232 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8233 emitcode ("jnz", "%05d$", lbl->key + 100);
8237 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8240 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8241 emitcode ("", "%05d$:", lbl->key + 100);
8242 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8243 emitcode ("", "%05d$:", lbl1->key + 100);
8245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8250 /*-----------------------------------------------------------------*/
8251 /* genReceive - generate code for a receive iCode */
8252 /*-----------------------------------------------------------------*/
8254 genReceive (iCode * ic)
8256 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8257 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8258 IS_TRUE_SYMOP (IC_RESULT (ic))))
8261 int size = getSize (operandType (IC_RESULT (ic)));
8262 int offset = fReturnSizeMCS51 - size;
8265 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8266 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8269 aopOp (IC_RESULT (ic), ic, FALSE);
8270 size = AOP_SIZE (IC_RESULT (ic));
8274 emitcode ("pop", "acc");
8275 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8282 aopOp (IC_RESULT (ic), ic, FALSE);
8284 assignResultValue (IC_RESULT (ic));
8287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8290 /*-----------------------------------------------------------------*/
8291 /* gen51Code - generate code for 8051 based controllers */
8292 /*-----------------------------------------------------------------*/
8294 gen51Code (iCode * lic)
8299 lineHead = lineCurr = NULL;
8301 /* print the allocation information */
8303 printAllocInfo (currFunc, codeOutFile);
8304 /* if debug information required */
8305 /* if (options.debug && currFunc) { */
8308 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8310 if (IS_STATIC (currFunc->etype))
8311 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8313 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8316 /* stack pointer name */
8317 if (options.useXstack)
8323 for (ic = lic; ic; ic = ic->next)
8326 if (cln != ic->lineno)
8331 emitcode ("", "C$%s$%d$%d$%d ==.",
8332 FileBaseName (ic->filename), ic->lineno,
8333 ic->level, ic->block);
8336 emitcode (";", "%s %d", ic->filename, ic->lineno);
8339 /* if the result is marked as
8340 spilt and rematerializable or code for
8341 this has already been generated then
8343 if (resultRemat (ic) || ic->generated)
8346 /* depending on the operation */
8366 /* IPOP happens only when trying to restore a
8367 spilt live range, if there is an ifx statement
8368 following this pop then the if statement might
8369 be using some of the registers being popped which
8370 would destory the contents of the register so
8371 we need to check for this condition and handle it */
8373 ic->next->op == IFX &&
8374 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8375 genIfx (ic->next, ic);
8393 genEndFunction (ic);
8413 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8430 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8434 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8441 /* note these two are xlated by algebraic equivalence
8442 during parsing SDCC.y */
8443 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8444 "got '>=' or '<=' shouldn't have come here");
8448 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8460 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8464 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8468 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8495 case GET_VALUE_AT_ADDRESS:
8500 if (POINTER_SET (ic))
8527 addSet (&_G.sendSet, ic);
8532 /* piCode(ic,stdout); */
8538 /* now we are ready to call the
8539 peep hole optimizer */
8540 if (!options.nopeep)
8541 peepHole (&lineHead);
8543 /* now do the actual printing */
8544 printLine (lineHead, codeOutFile);