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)
1118 if ((size = aop->size) <= 1)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1130 if (aop->type == AOP_DPTR2)
1136 emitcode ("lcall", "__decdptr");
1139 if (aop->type == AOP_DPTR2)
1149 #define AOP(op) op->aop
1150 #define AOP_TYPE(op) AOP(op)->type
1151 #define AOP_SIZE(op) AOP(op)->size
1152 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1153 AOP_TYPE(x) == AOP_R0))
1155 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1156 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1159 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1160 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1161 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1163 /*-----------------------------------------------------------------*/
1164 /* genNotFloat - generates not for float operations */
1165 /*-----------------------------------------------------------------*/
1167 genNotFloat (operand * op, operand * res)
1173 /* we will put 127 in the first byte of
1175 aopPut (AOP (res), "#127", 0);
1176 size = AOP_SIZE (op) - 1;
1179 l = aopGet (op->aop, offset++, FALSE, FALSE);
1184 emitcode ("orl", "a,%s",
1186 offset++, FALSE, FALSE));
1188 tlbl = newiTempLabel (NULL);
1190 tlbl = newiTempLabel (NULL);
1191 aopPut (res->aop, one, 1);
1192 emitcode ("jz", "%05d$", (tlbl->key + 100));
1193 aopPut (res->aop, zero, 1);
1194 emitcode ("", "%05d$:", (tlbl->key + 100));
1196 size = res->aop->size - 2;
1198 /* put zeros in the rest */
1200 aopPut (res->aop, zero, offset++);
1203 /*-----------------------------------------------------------------*/
1204 /* opIsGptr: returns non-zero if the passed operand is */
1205 /* a generic pointer type. */
1206 /*-----------------------------------------------------------------*/
1208 opIsGptr (operand * op)
1210 sym_link *type = operandType (op);
1212 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1219 /*-----------------------------------------------------------------*/
1220 /* getDataSize - get the operand data size */
1221 /*-----------------------------------------------------------------*/
1223 getDataSize (operand * op)
1226 size = AOP_SIZE (op);
1227 if (size == GPTRSIZE)
1229 sym_link *type = operandType (op);
1230 if (IS_GENPTR (type))
1232 /* generic pointer; arithmetic operations
1233 * should ignore the high byte (pointer type).
1241 /*-----------------------------------------------------------------*/
1242 /* outAcc - output Acc */
1243 /*-----------------------------------------------------------------*/
1245 outAcc (operand * result)
1248 size = getDataSize (result);
1251 aopPut (AOP (result), "a", 0);
1254 /* unsigned or positive */
1257 aopPut (AOP (result), zero, offset++);
1262 /*-----------------------------------------------------------------*/
1263 /* outBitC - output a bit C */
1264 /*-----------------------------------------------------------------*/
1266 outBitC (operand * result)
1268 /* if the result is bit */
1269 if (AOP_TYPE (result) == AOP_CRY)
1270 aopPut (AOP (result), "c", 0);
1273 emitcode ("clr", "a");
1274 emitcode ("rlc", "a");
1279 /*-----------------------------------------------------------------*/
1280 /* toBoolean - emit code for orl a,operator(sizeop) */
1281 /*-----------------------------------------------------------------*/
1283 toBoolean (operand * oper)
1285 int size = AOP_SIZE (oper) - 1;
1287 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1289 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1293 /*-----------------------------------------------------------------*/
1294 /* genNot - generate code for ! operation */
1295 /*-----------------------------------------------------------------*/
1300 sym_link *optype = operandType (IC_LEFT (ic));
1302 /* assign asmOps to operand & result */
1303 aopOp (IC_LEFT (ic), ic, FALSE);
1304 aopOp (IC_RESULT (ic), ic, TRUE);
1306 /* if in bit space then a special case */
1307 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1309 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1310 emitcode ("cpl", "c");
1311 outBitC (IC_RESULT (ic));
1315 /* if type float then do float */
1316 if (IS_FLOAT (optype))
1318 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1322 toBoolean (IC_LEFT (ic));
1324 tlbl = newiTempLabel (NULL);
1325 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1326 emitcode ("", "%05d$:", tlbl->key + 100);
1327 outBitC (IC_RESULT (ic));
1330 /* release the aops */
1331 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1332 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1336 /*-----------------------------------------------------------------*/
1337 /* genCpl - generate code for complement */
1338 /*-----------------------------------------------------------------*/
1346 /* assign asmOps to operand & result */
1347 aopOp (IC_LEFT (ic), ic, FALSE);
1348 aopOp (IC_RESULT (ic), ic, TRUE);
1350 /* if both are in bit space then
1352 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1353 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1356 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1357 emitcode ("cpl", "c");
1358 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1362 size = AOP_SIZE (IC_RESULT (ic));
1365 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1367 emitcode ("cpl", "a");
1368 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1373 /* release the aops */
1374 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1378 /*-----------------------------------------------------------------*/
1379 /* genUminusFloat - unary minus for floating points */
1380 /*-----------------------------------------------------------------*/
1382 genUminusFloat (operand * op, operand * result)
1384 int size, offset = 0;
1386 /* for this we just need to flip the
1387 first it then copy the rest in place */
1388 size = AOP_SIZE (op) - 1;
1389 l = aopGet (AOP (op), 3, FALSE, FALSE);
1393 emitcode ("cpl", "acc.7");
1394 aopPut (AOP (result), "a", 3);
1398 aopPut (AOP (result),
1399 aopGet (AOP (op), offset, FALSE, FALSE),
1405 /*-----------------------------------------------------------------*/
1406 /* genUminus - unary minus code generation */
1407 /*-----------------------------------------------------------------*/
1409 genUminus (iCode * ic)
1412 sym_link *optype, *rtype;
1416 aopOp (IC_LEFT (ic), ic, FALSE);
1417 aopOp (IC_RESULT (ic), ic, TRUE);
1419 /* if both in bit space then special
1421 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1422 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1425 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1426 emitcode ("cpl", "c");
1427 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1431 optype = operandType (IC_LEFT (ic));
1432 rtype = operandType (IC_RESULT (ic));
1434 /* if float then do float stuff */
1435 if (IS_FLOAT (optype))
1437 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1441 /* otherwise subtract from zero */
1442 size = AOP_SIZE (IC_LEFT (ic));
1447 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1448 if (!strcmp (l, "a"))
1452 emitcode ("cpl", "a");
1453 emitcode ("addc", "a,#0");
1459 emitcode ("clr", "a");
1460 emitcode ("subb", "a,%s", l);
1462 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1465 /* if any remaining bytes in the result */
1466 /* we just need to propagate the sign */
1467 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1469 emitcode ("rlc", "a");
1470 emitcode ("subb", "a,acc");
1472 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1476 /* release the aops */
1477 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1481 /*-----------------------------------------------------------------*/
1482 /* saveRegisters - will look for a call and save the registers */
1483 /*-----------------------------------------------------------------*/
1485 saveRegisters (iCode * lic)
1493 for (ic = lic; ic; ic = ic->next)
1494 if (ic->op == CALL || ic->op == PCALL)
1499 fprintf (stderr, "found parameter push with no function call\n");
1503 /* if the registers have been saved already then
1505 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1508 /* find the registers in use at this time
1509 and push them away to safety */
1510 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1514 if (options.useXstack)
1516 if (bitVectBitValue (rsave, R0_IDX))
1517 emitcode ("mov", "b,r0");
1518 emitcode ("mov", "r0,%s", spname);
1519 for (i = 0; i < mcs51_nRegs; i++)
1521 if (bitVectBitValue (rsave, i))
1524 emitcode ("mov", "a,b");
1526 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1527 emitcode ("movx", "@r0,a");
1528 emitcode ("inc", "r0");
1531 emitcode ("mov", "%s,r0", spname);
1532 if (bitVectBitValue (rsave, R0_IDX))
1533 emitcode ("mov", "r0,b");
1536 for (i = 0; i < mcs51_nRegs; i++)
1538 if (bitVectBitValue (rsave, i))
1539 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1542 detype = getSpec (operandType (IC_LEFT (ic)));
1544 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1545 IS_ISR (currFunc->etype) &&
1548 saverbank (SPEC_BANK (detype), ic, TRUE);
1551 /*-----------------------------------------------------------------*/
1552 /* unsaveRegisters - pop the pushed registers */
1553 /*-----------------------------------------------------------------*/
1555 unsaveRegisters (iCode * ic)
1559 /* find the registers in use at this time
1560 and push them away to safety */
1561 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1564 if (options.useXstack)
1566 emitcode ("mov", "r0,%s", spname);
1567 for (i = mcs51_nRegs; i >= 0; i--)
1569 if (bitVectBitValue (rsave, i))
1571 emitcode ("dec", "r0");
1572 emitcode ("movx", "a,@r0");
1574 emitcode ("mov", "b,a");
1576 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1580 emitcode ("mov", "%s,r0", spname);
1581 if (bitVectBitValue (rsave, R0_IDX))
1582 emitcode ("mov", "r0,b");
1585 for (i = mcs51_nRegs; i >= 0; i--)
1587 if (bitVectBitValue (rsave, i))
1588 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1594 /*-----------------------------------------------------------------*/
1596 /*-----------------------------------------------------------------*/
1598 pushSide (operand * oper, int size)
1603 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1604 if (AOP_TYPE (oper) != AOP_REG &&
1605 AOP_TYPE (oper) != AOP_DIR &&
1608 emitcode ("mov", "a,%s", l);
1609 emitcode ("push", "acc");
1612 emitcode ("push", "%s", l);
1616 /*-----------------------------------------------------------------*/
1617 /* assignResultValue - */
1618 /*-----------------------------------------------------------------*/
1620 assignResultValue (operand * oper)
1623 int size = AOP_SIZE (oper);
1626 aopPut (AOP (oper), fReturn[offset], offset);
1632 /*-----------------------------------------------------------------*/
1633 /* genXpush - pushes onto the external stack */
1634 /*-----------------------------------------------------------------*/
1636 genXpush (iCode * ic)
1638 asmop *aop = newAsmop (0);
1640 int size, offset = 0;
1642 aopOp (IC_LEFT (ic), ic, FALSE);
1643 r = getFreePtr (ic, &aop, FALSE);
1646 emitcode ("mov", "%s,_spx", r->name);
1648 size = AOP_SIZE (IC_LEFT (ic));
1652 char *l = aopGet (AOP (IC_LEFT (ic)),
1653 offset++, FALSE, FALSE);
1655 emitcode ("movx", "@%s,a", r->name);
1656 emitcode ("inc", "%s", r->name);
1661 emitcode ("mov", "_spx,%s", r->name);
1663 freeAsmop (NULL, aop, ic, TRUE);
1664 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1667 /*-----------------------------------------------------------------*/
1668 /* genIpush - genrate code for pushing this gets a little complex */
1669 /*-----------------------------------------------------------------*/
1671 genIpush (iCode * ic)
1673 int size, offset = 0;
1677 /* if this is not a parm push : ie. it is spill push
1678 and spill push is always done on the local stack */
1682 /* and the item is spilt then do nothing */
1683 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1686 aopOp (IC_LEFT (ic), ic, FALSE);
1687 size = AOP_SIZE (IC_LEFT (ic));
1688 /* push it on the stack */
1691 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1697 emitcode ("push", "%s", l);
1702 /* this is a paramter push: in this case we call
1703 the routine to find the call and save those
1704 registers that need to be saved */
1707 /* if use external stack then call the external
1708 stack pushing routine */
1709 if (options.useXstack)
1715 /* then do the push */
1716 aopOp (IC_LEFT (ic), ic, FALSE);
1719 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1720 size = AOP_SIZE (IC_LEFT (ic));
1724 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1725 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1726 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1729 emitcode ("mov", "a,%s", l);
1730 emitcode ("push", "acc");
1733 emitcode ("push", "%s", l);
1736 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1739 /*-----------------------------------------------------------------*/
1740 /* genIpop - recover the registers: can happen only for spilling */
1741 /*-----------------------------------------------------------------*/
1743 genIpop (iCode * ic)
1748 /* if the temp was not pushed then */
1749 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1752 aopOp (IC_LEFT (ic), ic, FALSE);
1753 size = AOP_SIZE (IC_LEFT (ic));
1754 offset = (size - 1);
1756 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1759 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1762 /*-----------------------------------------------------------------*/
1763 /* unsaverbank - restores the resgister bank from stack */
1764 /*-----------------------------------------------------------------*/
1766 unsaverbank (int bank, iCode * ic, bool popPsw)
1774 if (options.useXstack)
1777 r = getFreePtr (ic, &aop, FALSE);
1780 emitcode ("mov", "%s,_spx", r->name);
1781 emitcode ("movx", "a,@%s", r->name);
1782 emitcode ("mov", "psw,a");
1783 emitcode ("dec", "%s", r->name);
1787 emitcode ("pop", "psw");
1790 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1792 if (options.useXstack)
1794 emitcode ("movx", "a,@%s", r->name);
1795 emitcode ("mov", "(%s+%d),a",
1796 regs8051[i].base, 8 * bank + regs8051[i].offset);
1797 emitcode ("dec", "%s", r->name);
1801 emitcode ("pop", "(%s+%d)",
1802 regs8051[i].base, 8 * bank + regs8051[i].offset);
1805 if (options.useXstack)
1808 emitcode ("mov", "_spx,%s", r->name);
1809 freeAsmop (NULL, aop, ic, TRUE);
1814 /*-----------------------------------------------------------------*/
1815 /* saverbank - saves an entire register bank on the stack */
1816 /*-----------------------------------------------------------------*/
1818 saverbank (int bank, iCode * ic, bool pushPsw)
1824 if (options.useXstack)
1828 r = getFreePtr (ic, &aop, FALSE);
1829 emitcode ("mov", "%s,_spx", r->name);
1833 for (i = 0; i < mcs51_nRegs; i++)
1835 if (options.useXstack)
1837 emitcode ("inc", "%s", r->name);
1838 emitcode ("mov", "a,(%s+%d)",
1839 regs8051[i].base, 8 * bank + regs8051[i].offset);
1840 emitcode ("movx", "@%s,a", r->name);
1843 emitcode ("push", "(%s+%d)",
1844 regs8051[i].base, 8 * bank + regs8051[i].offset);
1849 if (options.useXstack)
1851 emitcode ("mov", "a,psw");
1852 emitcode ("movx", "@%s,a", r->name);
1853 emitcode ("inc", "%s", r->name);
1854 emitcode ("mov", "_spx,%s", r->name);
1855 freeAsmop (NULL, aop, ic, TRUE);
1859 emitcode ("push", "psw");
1861 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1867 /*-----------------------------------------------------------------*/
1868 /* genCall - generates a call statement */
1869 /*-----------------------------------------------------------------*/
1871 genCall (iCode * ic)
1875 /* if caller saves & we have not saved then */
1879 /* if we are calling a function that is not using
1880 the same register bank then we need to save the
1881 destination registers on the stack */
1882 detype = getSpec (operandType (IC_LEFT (ic)));
1884 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1885 IS_ISR (currFunc->etype) &&
1888 saverbank (SPEC_BANK (detype), ic, TRUE);
1890 /* if send set is not empty the assign */
1895 for (sic = setFirstItem (_G.sendSet); sic;
1896 sic = setNextItem (_G.sendSet))
1898 int size, offset = 0;
1899 aopOp (IC_LEFT (sic), sic, FALSE);
1900 size = AOP_SIZE (IC_LEFT (sic));
1903 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1905 if (strcmp (l, fReturn[offset]))
1906 emitcode ("mov", "%s,%s",
1911 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1916 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1917 OP_SYMBOL (IC_LEFT (ic))->rname :
1918 OP_SYMBOL (IC_LEFT (ic))->name));
1920 /* if we need assign a result value */
1921 if ((IS_ITEMP (IC_RESULT (ic)) &&
1922 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1923 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1924 IS_TRUE_SYMOP (IC_RESULT (ic)))
1928 aopOp (IC_RESULT (ic), ic, FALSE);
1931 assignResultValue (IC_RESULT (ic));
1933 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1936 /* adjust the stack for parameters if
1941 if (ic->parmBytes > 3)
1943 emitcode ("mov", "a,%s", spname);
1944 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1945 emitcode ("mov", "%s,a", spname);
1948 for (i = 0; i < ic->parmBytes; i++)
1949 emitcode ("dec", "%s", spname);
1953 /* if register bank was saved then pop them */
1955 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1957 /* if we hade saved some registers then unsave them */
1958 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1959 unsaveRegisters (ic);
1964 /*-----------------------------------------------------------------*/
1965 /* genPcall - generates a call by pointer statement */
1966 /*-----------------------------------------------------------------*/
1968 genPcall (iCode * ic)
1971 symbol *rlbl = newiTempLabel (NULL);
1974 /* if caller saves & we have not saved then */
1978 /* if we are calling a function that is not using
1979 the same register bank then we need to save the
1980 destination registers on the stack */
1981 detype = getSpec (operandType (IC_LEFT (ic)));
1983 IS_ISR (currFunc->etype) &&
1984 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
1985 saverbank (SPEC_BANK (detype), ic, TRUE);
1988 /* push the return address on to the stack */
1989 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
1990 emitcode ("push", "acc");
1991 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
1992 emitcode ("push", "acc");
1994 /* now push the calling address */
1995 aopOp (IC_LEFT (ic), ic, FALSE);
1997 pushSide (IC_LEFT (ic), FPTRSIZE);
1999 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2001 /* if send set is not empty the assign */
2006 for (sic = setFirstItem (_G.sendSet); sic;
2007 sic = setNextItem (_G.sendSet))
2009 int size, offset = 0;
2010 aopOp (IC_LEFT (sic), sic, FALSE);
2011 size = AOP_SIZE (IC_LEFT (sic));
2014 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2016 if (strcmp (l, fReturn[offset]))
2017 emitcode ("mov", "%s,%s",
2022 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2027 emitcode ("ret", "");
2028 emitcode ("", "%05d$:", (rlbl->key + 100));
2031 /* if we need assign a result value */
2032 if ((IS_ITEMP (IC_RESULT (ic)) &&
2033 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2034 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2035 IS_TRUE_SYMOP (IC_RESULT (ic)))
2039 aopOp (IC_RESULT (ic), ic, FALSE);
2042 assignResultValue (IC_RESULT (ic));
2044 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2047 /* adjust the stack for parameters if
2052 if (ic->parmBytes > 3)
2054 emitcode ("mov", "a,%s", spname);
2055 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2056 emitcode ("mov", "%s,a", spname);
2059 for (i = 0; i < ic->parmBytes; i++)
2060 emitcode ("dec", "%s", spname);
2064 /* if register bank was saved then unsave them */
2066 (SPEC_BANK (currFunc->etype) !=
2067 SPEC_BANK (detype)))
2068 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2070 /* if we hade saved some registers then
2073 unsaveRegisters (ic);
2077 /*-----------------------------------------------------------------*/
2078 /* resultRemat - result is rematerializable */
2079 /*-----------------------------------------------------------------*/
2081 resultRemat (iCode * ic)
2083 if (SKIP_IC (ic) || ic->op == IFX)
2086 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2088 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2089 if (sym->remat && !POINTER_SET (ic))
2096 #if defined(__BORLANDC__) || defined(_MSC_VER)
2097 #define STRCASECMP stricmp
2099 #define STRCASECMP strcasecmp
2102 /*-----------------------------------------------------------------*/
2103 /* inExcludeList - return 1 if the string is in exclude Reg list */
2104 /*-----------------------------------------------------------------*/
2106 inExcludeList (char *s)
2110 if (options.excludeRegs[i] &&
2111 STRCASECMP (options.excludeRegs[i], "none") == 0)
2114 for (i = 0; options.excludeRegs[i]; i++)
2116 if (options.excludeRegs[i] &&
2117 STRCASECMP (s, options.excludeRegs[i]) == 0)
2123 /*-----------------------------------------------------------------*/
2124 /* genFunction - generated code for function entry */
2125 /*-----------------------------------------------------------------*/
2127 genFunction (iCode * ic)
2133 /* create the function header */
2134 emitcode (";", "-----------------------------------------");
2135 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2136 emitcode (";", "-----------------------------------------");
2138 emitcode ("", "%s:", sym->rname);
2139 fetype = getSpec (operandType (IC_LEFT (ic)));
2141 /* if critical function then turn interrupts off */
2142 if (SPEC_CRTCL (fetype))
2143 emitcode ("clr", "ea");
2145 /* here we need to generate the equates for the
2146 register bank if required */
2147 if (SPEC_BANK (fetype) != rbank)
2151 rbank = SPEC_BANK (fetype);
2152 for (i = 0; i < mcs51_nRegs; i++)
2154 if (strcmp (regs8051[i].base, "0") == 0)
2155 emitcode ("", "%s = 0x%02x",
2157 8 * rbank + regs8051[i].offset);
2159 emitcode ("", "%s = %s + 0x%02x",
2162 8 * rbank + regs8051[i].offset);
2166 /* if this is an interrupt service routine then
2167 save acc, b, dpl, dph */
2168 if (IS_ISR (sym->etype))
2171 if (!inExcludeList ("acc"))
2172 emitcode ("push", "acc");
2173 if (!inExcludeList ("b"))
2174 emitcode ("push", "b");
2175 if (!inExcludeList ("dpl"))
2176 emitcode ("push", "dpl");
2177 if (!inExcludeList ("dph"))
2178 emitcode ("push", "dph");
2179 /* if this isr has no bank i.e. is going to
2180 run with bank 0 , then we need to save more
2182 if (!SPEC_BANK (sym->etype))
2185 /* if this function does not call any other
2186 function then we can be economical and
2187 save only those registers that are used */
2192 /* if any registers used */
2195 /* save the registers used */
2196 for (i = 0; i < sym->regsUsed->size; i++)
2198 if (bitVectBitValue (sym->regsUsed, i) ||
2199 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2200 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2207 /* this function has a function call cannot
2208 determines register usage so we will have the
2210 saverbank (0, ic, FALSE);
2216 /* if callee-save to be used for this function
2217 then save the registers being used in this function */
2218 if (sym->calleeSave)
2222 /* if any registers used */
2225 /* save the registers used */
2226 for (i = 0; i < sym->regsUsed->size; i++)
2228 if (bitVectBitValue (sym->regsUsed, i) ||
2229 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2231 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2239 /* set the register bank to the desired value */
2240 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2242 emitcode ("push", "psw");
2243 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2246 if (IS_RENT (sym->etype) || options.stackAuto)
2249 if (options.useXstack)
2251 emitcode ("mov", "r0,%s", spname);
2252 emitcode ("mov", "a,_bp");
2253 emitcode ("movx", "@r0,a");
2254 emitcode ("inc", "%s", spname);
2258 /* set up the stack */
2259 emitcode ("push", "_bp"); /* save the callers stack */
2261 emitcode ("mov", "_bp,%s", spname);
2264 /* adjust the stack for the function */
2270 werror (W_STACK_OVERFLOW, sym->name);
2272 if (i > 3 && sym->recvSize < 4)
2275 emitcode ("mov", "a,sp");
2276 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2277 emitcode ("mov", "sp,a");
2282 emitcode ("inc", "sp");
2288 emitcode ("mov", "a,_spx");
2289 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2290 emitcode ("mov", "_spx,a");
2295 /*-----------------------------------------------------------------*/
2296 /* genEndFunction - generates epilogue for functions */
2297 /*-----------------------------------------------------------------*/
2299 genEndFunction (iCode * ic)
2301 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2303 if (IS_RENT (sym->etype) || options.stackAuto)
2305 emitcode ("mov", "%s,_bp", spname);
2308 /* if use external stack but some variables were
2309 added to the local stack then decrement the
2311 if (options.useXstack && sym->stack)
2313 emitcode ("mov", "a,sp");
2314 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2315 emitcode ("mov", "sp,a");
2319 if ((IS_RENT (sym->etype) || options.stackAuto))
2321 if (options.useXstack)
2323 emitcode ("mov", "r0,%s", spname);
2324 emitcode ("movx", "a,@r0");
2325 emitcode ("mov", "_bp,a");
2326 emitcode ("dec", "%s", spname);
2330 emitcode ("pop", "_bp");
2334 /* restore the register bank */
2335 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2336 emitcode ("pop", "psw");
2338 if (IS_ISR (sym->etype))
2341 /* now we need to restore the registers */
2342 /* if this isr has no bank i.e. is going to
2343 run with bank 0 , then we need to save more
2345 if (!SPEC_BANK (sym->etype))
2348 /* if this function does not call any other
2349 function then we can be economical and
2350 save only those registers that are used */
2355 /* if any registers used */
2358 /* save the registers used */
2359 for (i = sym->regsUsed->size; i >= 0; i--)
2361 if (bitVectBitValue (sym->regsUsed, i) ||
2362 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2363 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2370 /* this function has a function call cannot
2371 determines register usage so we will have the
2373 unsaverbank (0, ic, FALSE);
2377 if (!inExcludeList ("dph"))
2378 emitcode ("pop", "dph");
2379 if (!inExcludeList ("dpl"))
2380 emitcode ("pop", "dpl");
2381 if (!inExcludeList ("b"))
2382 emitcode ("pop", "b");
2383 if (!inExcludeList ("acc"))
2384 emitcode ("pop", "acc");
2386 if (SPEC_CRTCL (sym->etype))
2387 emitcode ("setb", "ea");
2389 /* if debug then send end of function */
2390 /* if (options.debug && currFunc) { */
2394 emitcode ("", "C$%s$%d$%d$%d ==.",
2395 FileBaseName (ic->filename), currFunc->lastLine,
2396 ic->level, ic->block);
2397 if (IS_STATIC (currFunc->etype))
2398 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2400 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2404 emitcode ("reti", "");
2408 if (SPEC_CRTCL (sym->etype))
2409 emitcode ("setb", "ea");
2411 if (sym->calleeSave)
2415 /* if any registers used */
2418 /* save the registers used */
2419 for (i = sym->regsUsed->size; i >= 0; i--)
2421 if (bitVectBitValue (sym->regsUsed, i) ||
2422 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2423 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2429 /* if debug then send end of function */
2433 emitcode ("", "C$%s$%d$%d$%d ==.",
2434 FileBaseName (ic->filename), currFunc->lastLine,
2435 ic->level, ic->block);
2436 if (IS_STATIC (currFunc->etype))
2437 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2439 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2443 emitcode ("ret", "");
2448 /*-----------------------------------------------------------------*/
2449 /* genRet - generate code for return statement */
2450 /*-----------------------------------------------------------------*/
2454 int size, offset = 0, pushed = 0;
2456 /* if we have no return value then
2457 just generate the "ret" */
2461 /* we have something to return then
2462 move the return value into place */
2463 aopOp (IC_LEFT (ic), ic, FALSE);
2464 size = AOP_SIZE (IC_LEFT (ic));
2469 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2472 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2474 emitcode ("push", "%s", l);
2479 l = aopGet (AOP (IC_LEFT (ic)), offset,
2481 if (strcmp (fReturn[offset], l))
2482 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2491 if (strcmp (fReturn[pushed], "a"))
2492 emitcode ("pop", fReturn[pushed]);
2494 emitcode ("pop", "acc");
2497 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2500 /* generate a jump to the return label
2501 if the next is not the return statement */
2502 if (!(ic->next && ic->next->op == LABEL &&
2503 IC_LABEL (ic->next) == returnLabel))
2505 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2509 /*-----------------------------------------------------------------*/
2510 /* genLabel - generates a label */
2511 /*-----------------------------------------------------------------*/
2513 genLabel (iCode * ic)
2515 /* special case never generate */
2516 if (IC_LABEL (ic) == entryLabel)
2519 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2522 /*-----------------------------------------------------------------*/
2523 /* genGoto - generates a ljmp */
2524 /*-----------------------------------------------------------------*/
2526 genGoto (iCode * ic)
2528 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2531 /*-----------------------------------------------------------------*/
2532 /* findLabelBackwards: walks back through the iCode chain looking */
2533 /* for the given label. Returns number of iCode instructions */
2534 /* between that label and given ic. */
2535 /* Returns zero if label not found. */
2536 /*-----------------------------------------------------------------*/
2538 findLabelBackwards (iCode * ic, int key)
2547 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2549 /* printf("findLabelBackwards = %d\n", count); */
2557 /*-----------------------------------------------------------------*/
2558 /* genPlusIncr :- does addition with increment if possible */
2559 /*-----------------------------------------------------------------*/
2561 genPlusIncr (iCode * ic)
2563 unsigned int icount;
2564 unsigned int size = getDataSize (IC_RESULT (ic));
2566 /* will try to generate an increment */
2567 /* if the right side is not a literal
2569 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2572 /* if the literal value of the right hand side
2573 is greater than 4 then it is not worth it */
2574 if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2577 /* if increment 16 bits in register */
2578 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2586 /* If the next instruction is a goto and the goto target
2587 * is < 10 instructions previous to this, we can generate
2588 * jumps straight to that target.
2590 if (ic->next && ic->next->op == GOTO
2591 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2592 && labelRange <= 10)
2594 emitcode (";", "tail increment optimized");
2595 tlbl = IC_LABEL (ic->next);
2600 tlbl = newiTempLabel (NULL);
2603 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2604 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2605 IS_AOP_PREG (IC_RESULT (ic)))
2606 emitcode ("cjne", "%s,#0x00,%05d$"
2607 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2611 emitcode ("clr", "a");
2612 emitcode ("cjne", "a,%s,%05d$"
2613 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2617 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2620 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2621 IS_AOP_PREG (IC_RESULT (ic)))
2622 emitcode ("cjne", "%s,#0x00,%05d$"
2623 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2626 emitcode ("cjne", "a,%s,%05d$"
2627 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2630 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2635 IS_AOP_PREG (IC_RESULT (ic)))
2636 emitcode ("cjne", "%s,#0x00,%05d$"
2637 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2641 emitcode ("cjne", "a,%s,%05d$"
2642 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2645 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2650 emitcode ("", "%05d$:", tlbl->key + 100);
2655 /* if the sizes are greater than 1 then we cannot */
2656 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2657 AOP_SIZE (IC_LEFT (ic)) > 1)
2660 /* we can if the aops of the left & result match or
2661 if they are in registers and the registers are the
2663 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2668 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2669 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2670 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2676 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2685 /*-----------------------------------------------------------------*/
2686 /* outBitAcc - output a bit in acc */
2687 /*-----------------------------------------------------------------*/
2689 outBitAcc (operand * result)
2691 symbol *tlbl = newiTempLabel (NULL);
2692 /* if the result is a bit */
2693 if (AOP_TYPE (result) == AOP_CRY)
2695 aopPut (AOP (result), "a", 0);
2699 emitcode ("jz", "%05d$", tlbl->key + 100);
2700 emitcode ("mov", "a,%s", one);
2701 emitcode ("", "%05d$:", tlbl->key + 100);
2706 /*-----------------------------------------------------------------*/
2707 /* genPlusBits - generates code for addition of two bits */
2708 /*-----------------------------------------------------------------*/
2710 genPlusBits (iCode * ic)
2712 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2714 symbol *lbl = newiTempLabel (NULL);
2715 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2716 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2717 emitcode ("cpl", "c");
2718 emitcode ("", "%05d$:", (lbl->key + 100));
2719 outBitC (IC_RESULT (ic));
2723 emitcode ("clr", "a");
2724 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2725 emitcode ("rlc", "a");
2726 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2727 emitcode ("addc", "a,#0x00");
2728 outAcc (IC_RESULT (ic));
2733 /* This is the original version of this code.
2735 * This is being kept around for reference,
2736 * because I am not entirely sure I got it right...
2739 adjustArithmeticResult (iCode * ic)
2741 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2742 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2743 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2744 aopPut (AOP (IC_RESULT (ic)),
2745 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2748 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2749 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2750 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2751 aopPut (AOP (IC_RESULT (ic)),
2752 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2755 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2756 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2757 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2758 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2759 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2762 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2763 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2767 /* This is the pure and virtuous version of this code.
2768 * I'm pretty certain it's right, but not enough to toss the old
2772 adjustArithmeticResult (iCode * ic)
2774 if (opIsGptr (IC_RESULT (ic)) &&
2775 opIsGptr (IC_LEFT (ic)) &&
2776 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2778 aopPut (AOP (IC_RESULT (ic)),
2779 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2783 if (opIsGptr (IC_RESULT (ic)) &&
2784 opIsGptr (IC_RIGHT (ic)) &&
2785 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2787 aopPut (AOP (IC_RESULT (ic)),
2788 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2792 if (opIsGptr (IC_RESULT (ic)) &&
2793 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2794 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2795 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2796 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2799 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2800 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2805 /*-----------------------------------------------------------------*/
2806 /* genPlus - generates code for addition */
2807 /*-----------------------------------------------------------------*/
2809 genPlus (iCode * ic)
2811 int size, offset = 0;
2813 /* special cases :- */
2815 aopOp (IC_LEFT (ic), ic, FALSE);
2816 aopOp (IC_RIGHT (ic), ic, FALSE);
2817 aopOp (IC_RESULT (ic), ic, TRUE);
2819 /* if literal, literal on the right or
2820 if left requires ACC or right is already
2822 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2823 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2824 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2826 operand *t = IC_RIGHT (ic);
2827 IC_RIGHT (ic) = IC_LEFT (ic);
2831 /* if both left & right are in bit
2833 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2834 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2840 /* if left in bit space & right literal */
2841 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2842 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2844 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2845 /* if result in bit space */
2846 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2848 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2849 emitcode ("cpl", "c");
2850 outBitC (IC_RESULT (ic));
2854 size = getDataSize (IC_RESULT (ic));
2857 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2858 emitcode ("addc", "a,#00");
2859 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2865 /* if I can do an increment instead
2866 of add then GOOD for ME */
2867 if (genPlusIncr (ic) == TRUE)
2870 size = getDataSize (IC_RESULT (ic));
2874 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2876 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2878 emitcode ("add", "a,%s",
2879 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2881 emitcode ("addc", "a,%s",
2882 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2886 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2888 emitcode ("add", "a,%s",
2889 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2891 emitcode ("addc", "a,%s",
2892 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2894 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2897 adjustArithmeticResult (ic);
2900 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2901 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2902 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2905 /*-----------------------------------------------------------------*/
2906 /* genMinusDec :- does subtraction with deccrement if possible */
2907 /*-----------------------------------------------------------------*/
2909 genMinusDec (iCode * ic)
2911 unsigned int icount;
2912 unsigned int size = getDataSize (IC_RESULT (ic));
2914 /* will try to generate an increment */
2915 /* if the right side is not a literal
2917 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2920 /* if the literal value of the right hand side
2921 is greater than 4 then it is not worth it */
2922 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2925 /* if decrement 16 bits in register */
2926 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2934 /* If the next instruction is a goto and the goto target
2935 * is <= 10 instructions previous to this, we can generate
2936 * jumps straight to that target.
2938 if (ic->next && ic->next->op == GOTO
2939 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2940 && labelRange <= 10)
2942 emitcode (";", "tail decrement optimized");
2943 tlbl = IC_LABEL (ic->next);
2948 tlbl = newiTempLabel (NULL);
2952 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2953 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2954 IS_AOP_PREG (IC_RESULT (ic)))
2955 emitcode ("cjne", "%s,#0xff,%05d$"
2956 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2960 emitcode ("mov", "a,#0xff");
2961 emitcode ("cjne", "a,%s,%05d$"
2962 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2965 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2969 IS_AOP_PREG (IC_RESULT (ic)))
2970 emitcode ("cjne", "%s,#0xff,%05d$"
2971 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2975 emitcode ("cjne", "a,%s,%05d$"
2976 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2979 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2983 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2984 IS_AOP_PREG (IC_RESULT (ic)))
2985 emitcode ("cjne", "%s,#0xff,%05d$"
2986 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2990 emitcode ("cjne", "a,%s,%05d$"
2991 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2994 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2998 emitcode ("", "%05d$:", tlbl->key + 100);
3003 /* if the sizes are greater than 1 then we cannot */
3004 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3005 AOP_SIZE (IC_LEFT (ic)) > 1)
3008 /* we can if the aops of the left & result match or
3009 if they are in registers and the registers are the
3011 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3015 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3023 /*-----------------------------------------------------------------*/
3024 /* addSign - complete with sign */
3025 /*-----------------------------------------------------------------*/
3027 addSign (operand * result, int offset, int sign)
3029 int size = (getDataSize (result) - offset);
3034 emitcode ("rlc", "a");
3035 emitcode ("subb", "a,acc");
3037 aopPut (AOP (result), "a", offset++);
3041 aopPut (AOP (result), zero, offset++);
3045 /*-----------------------------------------------------------------*/
3046 /* genMinusBits - generates code for subtraction of two bits */
3047 /*-----------------------------------------------------------------*/
3049 genMinusBits (iCode * ic)
3051 symbol *lbl = newiTempLabel (NULL);
3052 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3054 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3055 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3056 emitcode ("cpl", "c");
3057 emitcode ("", "%05d$:", (lbl->key + 100));
3058 outBitC (IC_RESULT (ic));
3062 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3063 emitcode ("subb", "a,acc");
3064 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3065 emitcode ("inc", "a");
3066 emitcode ("", "%05d$:", (lbl->key + 100));
3067 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3068 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3072 /*-----------------------------------------------------------------*/
3073 /* genMinus - generates code for subtraction */
3074 /*-----------------------------------------------------------------*/
3076 genMinus (iCode * ic)
3078 int size, offset = 0;
3079 unsigned long lit = 0L;
3081 aopOp (IC_LEFT (ic), ic, FALSE);
3082 aopOp (IC_RIGHT (ic), ic, FALSE);
3083 aopOp (IC_RESULT (ic), ic, TRUE);
3085 /* special cases :- */
3086 /* if both left & right are in bit space */
3087 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3088 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3094 /* if I can do an decrement instead
3095 of subtract then GOOD for ME */
3096 if (genMinusDec (ic) == TRUE)
3099 size = getDataSize (IC_RESULT (ic));
3101 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3107 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3111 /* if literal, add a,#-lit, else normal subb */
3114 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3115 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3116 emitcode ("subb", "a,%s",
3117 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3120 /* first add without previous c */
3122 emitcode ("add", "a,#0x%02x",
3123 (unsigned int) (lit & 0x0FFL));
3125 emitcode ("addc", "a,#0x%02x",
3126 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3128 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3131 adjustArithmeticResult (ic);
3134 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3135 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3136 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3140 /*-----------------------------------------------------------------*/
3141 /* genMultbits :- multiplication of bits */
3142 /*-----------------------------------------------------------------*/
3144 genMultbits (operand * left,
3148 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3149 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3154 /*-----------------------------------------------------------------*/
3155 /* genMultOneByte : 8 bit multiplication & division */
3156 /*-----------------------------------------------------------------*/
3158 genMultOneByte (operand * left,
3162 sym_link *opetype = operandType (result);
3167 /* (if two literals, the value is computed before) */
3168 /* if one literal, literal on the right */
3169 if (AOP_TYPE (left) == AOP_LIT)
3176 size = AOP_SIZE (result);
3177 /* signed or unsigned */
3178 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3179 l = aopGet (AOP (left), 0, FALSE, FALSE);
3181 emitcode ("mul", "ab");
3182 /* if result size = 1, mul signed = mul unsigned */
3183 aopPut (AOP (result), "a", 0);
3186 if (SPEC_USIGN (opetype))
3188 aopPut (AOP (result), "b", 1);
3190 /* for filling the MSBs */
3191 emitcode ("clr", "a");
3195 emitcode ("mov", "a,b");
3197 /* adjust the MSB if left or right neg */
3199 /* if one literal */
3200 if (AOP_TYPE (right) == AOP_LIT)
3202 /* AND literal negative */
3203 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3205 /* adjust MSB (c==0 after mul) */
3206 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3211 lbl = newiTempLabel (NULL);
3212 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3213 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3214 emitcode ("", "%05d$:", (lbl->key + 100));
3215 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3216 lbl = newiTempLabel (NULL);
3217 emitcode ("jc", "%05d$", (lbl->key + 100));
3218 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3219 emitcode ("", "%05d$:", (lbl->key + 100));
3222 lbl = newiTempLabel (NULL);
3223 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3224 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3225 emitcode ("", "%05d$:", (lbl->key + 100));
3226 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3227 lbl = newiTempLabel (NULL);
3228 emitcode ("jc", "%05d$", (lbl->key + 100));
3229 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3230 emitcode ("", "%05d$:", (lbl->key + 100));
3232 aopPut (AOP (result), "a", 1);
3236 emitcode ("rlc", "a");
3237 emitcode ("subb", "a,acc");
3244 aopPut (AOP (result), "a", offset++);
3248 /*-----------------------------------------------------------------*/
3249 /* genMult - generates code for multiplication */
3250 /*-----------------------------------------------------------------*/
3252 genMult (iCode * ic)
3254 operand *left = IC_LEFT (ic);
3255 operand *right = IC_RIGHT (ic);
3256 operand *result = IC_RESULT (ic);
3258 /* assign the amsops */
3259 aopOp (left, ic, FALSE);
3260 aopOp (right, ic, FALSE);
3261 aopOp (result, ic, TRUE);
3263 /* special cases first */
3265 if (AOP_TYPE (left) == AOP_CRY &&
3266 AOP_TYPE (right) == AOP_CRY)
3268 genMultbits (left, right, result);
3272 /* if both are of size == 1 */
3273 if (AOP_SIZE (left) == 1 &&
3274 AOP_SIZE (right) == 1)
3276 genMultOneByte (left, right, result);
3280 /* should have been converted to function call */
3284 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3286 freeAsmop (result, NULL, ic, TRUE);
3289 /*-----------------------------------------------------------------*/
3290 /* genDivbits :- division of bits */
3291 /*-----------------------------------------------------------------*/
3293 genDivbits (operand * left,
3300 /* the result must be bit */
3301 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3302 l = aopGet (AOP (left), 0, FALSE, FALSE);
3306 emitcode ("div", "ab");
3307 emitcode ("rrc", "a");
3308 aopPut (AOP (result), "c", 0);
3311 /*-----------------------------------------------------------------*/
3312 /* genDivOneByte : 8 bit division */
3313 /*-----------------------------------------------------------------*/
3315 genDivOneByte (operand * left,
3319 sym_link *opetype = operandType (result);
3324 size = AOP_SIZE (result) - 1;
3326 /* signed or unsigned */
3327 if (SPEC_USIGN (opetype))
3329 /* unsigned is easy */
3330 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3331 l = aopGet (AOP (left), 0, FALSE, FALSE);
3333 emitcode ("div", "ab");
3334 aopPut (AOP (result), "a", 0);
3336 aopPut (AOP (result), zero, offset++);
3340 /* signed is a little bit more difficult */
3342 /* save the signs of the operands */
3343 l = aopGet (AOP (left), 0, FALSE, FALSE);
3345 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3346 emitcode ("push", "acc"); /* save it on the stack */
3348 /* now sign adjust for both left & right */
3349 l = aopGet (AOP (right), 0, FALSE, FALSE);
3351 lbl = newiTempLabel (NULL);
3352 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3353 emitcode ("cpl", "a");
3354 emitcode ("inc", "a");
3355 emitcode ("", "%05d$:", (lbl->key + 100));
3356 emitcode ("mov", "b,a");
3358 /* sign adjust left side */
3359 l = aopGet (AOP (left), 0, FALSE, FALSE);
3362 lbl = newiTempLabel (NULL);
3363 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3364 emitcode ("cpl", "a");
3365 emitcode ("inc", "a");
3366 emitcode ("", "%05d$:", (lbl->key + 100));
3368 /* now the division */
3369 emitcode ("div", "ab");
3370 /* we are interested in the lower order
3372 emitcode ("mov", "b,a");
3373 lbl = newiTempLabel (NULL);
3374 emitcode ("pop", "acc");
3375 /* if there was an over flow we don't
3376 adjust the sign of the result */
3377 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3378 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3380 emitcode ("clr", "a");
3381 emitcode ("subb", "a,b");
3382 emitcode ("mov", "b,a");
3383 emitcode ("", "%05d$:", (lbl->key + 100));
3385 /* now we are done */
3386 aopPut (AOP (result), "b", 0);
3389 emitcode ("mov", "c,b.7");
3390 emitcode ("subb", "a,acc");
3393 aopPut (AOP (result), "a", offset++);
3397 /*-----------------------------------------------------------------*/
3398 /* genDiv - generates code for division */
3399 /*-----------------------------------------------------------------*/
3403 operand *left = IC_LEFT (ic);
3404 operand *right = IC_RIGHT (ic);
3405 operand *result = IC_RESULT (ic);
3407 /* assign the amsops */
3408 aopOp (left, ic, FALSE);
3409 aopOp (right, ic, FALSE);
3410 aopOp (result, ic, TRUE);
3412 /* special cases first */
3414 if (AOP_TYPE (left) == AOP_CRY &&
3415 AOP_TYPE (right) == AOP_CRY)
3417 genDivbits (left, right, result);
3421 /* if both are of size == 1 */
3422 if (AOP_SIZE (left) == 1 &&
3423 AOP_SIZE (right) == 1)
3425 genDivOneByte (left, right, result);
3429 /* should have been converted to function call */
3432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3434 freeAsmop (result, NULL, ic, TRUE);
3437 /*-----------------------------------------------------------------*/
3438 /* genModbits :- modulus of bits */
3439 /*-----------------------------------------------------------------*/
3441 genModbits (operand * left,
3448 /* the result must be bit */
3449 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3450 l = aopGet (AOP (left), 0, FALSE, FALSE);
3454 emitcode ("div", "ab");
3455 emitcode ("mov", "a,b");
3456 emitcode ("rrc", "a");
3457 aopPut (AOP (result), "c", 0);
3460 /*-----------------------------------------------------------------*/
3461 /* genModOneByte : 8 bit modulus */
3462 /*-----------------------------------------------------------------*/
3464 genModOneByte (operand * left,
3468 sym_link *opetype = operandType (result);
3472 /* signed or unsigned */
3473 if (SPEC_USIGN (opetype))
3475 /* unsigned is easy */
3476 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3477 l = aopGet (AOP (left), 0, FALSE, FALSE);
3479 emitcode ("div", "ab");
3480 aopPut (AOP (result), "b", 0);
3484 /* signed is a little bit more difficult */
3486 /* save the signs of the operands */
3487 l = aopGet (AOP (left), 0, FALSE, FALSE);
3490 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3491 emitcode ("push", "acc"); /* save it on the stack */
3493 /* now sign adjust for both left & right */
3494 l = aopGet (AOP (right), 0, FALSE, FALSE);
3497 lbl = newiTempLabel (NULL);
3498 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3499 emitcode ("cpl", "a");
3500 emitcode ("inc", "a");
3501 emitcode ("", "%05d$:", (lbl->key + 100));
3502 emitcode ("mov", "b,a");
3504 /* sign adjust left side */
3505 l = aopGet (AOP (left), 0, FALSE, FALSE);
3508 lbl = newiTempLabel (NULL);
3509 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3510 emitcode ("cpl", "a");
3511 emitcode ("inc", "a");
3512 emitcode ("", "%05d$:", (lbl->key + 100));
3514 /* now the multiplication */
3515 emitcode ("div", "ab");
3516 /* we are interested in the lower order
3518 lbl = newiTempLabel (NULL);
3519 emitcode ("pop", "acc");
3520 /* if there was an over flow we don't
3521 adjust the sign of the result */
3522 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3523 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3525 emitcode ("clr", "a");
3526 emitcode ("subb", "a,b");
3527 emitcode ("mov", "b,a");
3528 emitcode ("", "%05d$:", (lbl->key + 100));
3530 /* now we are done */
3531 aopPut (AOP (result), "b", 0);
3535 /*-----------------------------------------------------------------*/
3536 /* genMod - generates code for division */
3537 /*-----------------------------------------------------------------*/
3541 operand *left = IC_LEFT (ic);
3542 operand *right = IC_RIGHT (ic);
3543 operand *result = IC_RESULT (ic);
3545 /* assign the amsops */
3546 aopOp (left, ic, FALSE);
3547 aopOp (right, ic, FALSE);
3548 aopOp (result, ic, TRUE);
3550 /* special cases first */
3552 if (AOP_TYPE (left) == AOP_CRY &&
3553 AOP_TYPE (right) == AOP_CRY)
3555 genModbits (left, right, result);
3559 /* if both are of size == 1 */
3560 if (AOP_SIZE (left) == 1 &&
3561 AOP_SIZE (right) == 1)
3563 genModOneByte (left, right, result);
3567 /* should have been converted to function call */
3571 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3572 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3573 freeAsmop (result, NULL, ic, TRUE);
3576 /*-----------------------------------------------------------------*/
3577 /* genIfxJump :- will create a jump depending on the ifx */
3578 /*-----------------------------------------------------------------*/
3580 genIfxJump (iCode * ic, char *jval)
3583 symbol *tlbl = newiTempLabel (NULL);
3586 /* if true label then we jump if condition
3590 jlbl = IC_TRUE (ic);
3591 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3592 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3596 /* false label is present */
3597 jlbl = IC_FALSE (ic);
3598 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3599 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3601 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3602 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3604 emitcode (inst, "%05d$", tlbl->key + 100);
3605 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3606 emitcode ("", "%05d$:", tlbl->key + 100);
3608 /* mark the icode as generated */
3612 /*-----------------------------------------------------------------*/
3613 /* genCmp :- greater or less than comparison */
3614 /*-----------------------------------------------------------------*/
3616 genCmp (operand * left, operand * right,
3617 operand * result, iCode * ifx, int sign)
3619 int size, offset = 0;
3620 unsigned long lit = 0L;
3622 /* if left & right are bit variables */
3623 if (AOP_TYPE (left) == AOP_CRY &&
3624 AOP_TYPE (right) == AOP_CRY)
3626 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3627 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3631 /* subtract right from left if at the
3632 end the carry flag is set then we know that
3633 left is greater than right */
3634 size = max (AOP_SIZE (left), AOP_SIZE (right));
3636 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3637 if ((size == 1) && !sign &&
3638 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3640 symbol *lbl = newiTempLabel (NULL);
3641 emitcode ("cjne", "%s,%s,%05d$",
3642 aopGet (AOP (left), offset, FALSE, FALSE),
3643 aopGet (AOP (right), offset, FALSE, FALSE),
3645 emitcode ("", "%05d$:", lbl->key + 100);
3649 if (AOP_TYPE (right) == AOP_LIT)
3651 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3652 /* optimize if(x < 0) or if(x >= 0) */
3661 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3662 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3664 genIfxJump (ifx, "acc.7");
3668 emitcode ("rlc", "a");
3676 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3677 if (sign && size == 0)
3679 emitcode ("xrl", "a,#0x80");
3680 if (AOP_TYPE (right) == AOP_LIT)
3682 unsigned long lit = (unsigned long)
3683 floatFromVal (AOP (right)->aopu.aop_lit);
3684 emitcode ("subb", "a,#0x%02x",
3685 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3689 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3690 emitcode ("xrl", "b,#0x80");
3691 emitcode ("subb", "a,b");
3695 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3701 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3707 /* if the result is used in the next
3708 ifx conditional branch then generate
3709 code a little differently */
3711 genIfxJump (ifx, "c");
3714 /* leave the result in acc */
3718 /*-----------------------------------------------------------------*/
3719 /* genCmpGt :- greater than comparison */
3720 /*-----------------------------------------------------------------*/
3722 genCmpGt (iCode * ic, iCode * ifx)
3724 operand *left, *right, *result;
3725 sym_link *letype, *retype;
3728 left = IC_LEFT (ic);
3729 right = IC_RIGHT (ic);
3730 result = IC_RESULT (ic);
3732 letype = getSpec (operandType (left));
3733 retype = getSpec (operandType (right));
3734 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3735 /* assign the amsops */
3736 aopOp (left, ic, FALSE);
3737 aopOp (right, ic, FALSE);
3738 aopOp (result, ic, TRUE);
3740 genCmp (right, left, result, ifx, sign);
3742 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3743 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3744 freeAsmop (result, NULL, ic, TRUE);
3747 /*-----------------------------------------------------------------*/
3748 /* genCmpLt - less than comparisons */
3749 /*-----------------------------------------------------------------*/
3751 genCmpLt (iCode * ic, iCode * ifx)
3753 operand *left, *right, *result;
3754 sym_link *letype, *retype;
3757 left = IC_LEFT (ic);
3758 right = IC_RIGHT (ic);
3759 result = IC_RESULT (ic);
3761 letype = getSpec (operandType (left));
3762 retype = getSpec (operandType (right));
3763 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3765 /* assign the amsops */
3766 aopOp (left, ic, FALSE);
3767 aopOp (right, ic, FALSE);
3768 aopOp (result, ic, TRUE);
3770 genCmp (left, right, result, ifx, sign);
3772 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3774 freeAsmop (result, NULL, ic, TRUE);
3777 /*-----------------------------------------------------------------*/
3778 /* gencjneshort - compare and jump if not equal */
3779 /*-----------------------------------------------------------------*/
3781 gencjneshort (operand * left, operand * right, symbol * lbl)
3783 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3785 unsigned long lit = 0L;
3787 /* if the left side is a literal or
3788 if the right is in a pointer register and left
3790 if ((AOP_TYPE (left) == AOP_LIT) ||
3791 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3797 if (AOP_TYPE (right) == AOP_LIT)
3798 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3800 /* if the right side is a literal then anything goes */
3801 if (AOP_TYPE (right) == AOP_LIT &&
3802 AOP_TYPE (left) != AOP_DIR)
3806 emitcode ("cjne", "%s,%s,%05d$",
3807 aopGet (AOP (left), offset, FALSE, FALSE),
3808 aopGet (AOP (right), offset, FALSE, FALSE),
3814 /* if the right side is in a register or in direct space or
3815 if the left is a pointer register & right is not */
3816 else if (AOP_TYPE (right) == AOP_REG ||
3817 AOP_TYPE (right) == AOP_DIR ||
3818 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3819 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3823 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3824 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3825 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3826 emitcode ("jnz", "%05d$", lbl->key + 100);
3828 emitcode ("cjne", "a,%s,%05d$",
3829 aopGet (AOP (right), offset, FALSE, TRUE),
3836 /* right is a pointer reg need both a & b */
3839 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3840 if (strcmp (l, "b"))
3841 emitcode ("mov", "b,%s", l);
3842 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3843 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3849 /*-----------------------------------------------------------------*/
3850 /* gencjne - compare and jump if not equal */
3851 /*-----------------------------------------------------------------*/
3853 gencjne (operand * left, operand * right, symbol * lbl)
3855 symbol *tlbl = newiTempLabel (NULL);
3857 gencjneshort (left, right, lbl);
3859 emitcode ("mov", "a,%s", one);
3860 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3861 emitcode ("", "%05d$:", lbl->key + 100);
3862 emitcode ("clr", "a");
3863 emitcode ("", "%05d$:", tlbl->key + 100);
3866 /*-----------------------------------------------------------------*/
3867 /* genCmpEq - generates code for equal to */
3868 /*-----------------------------------------------------------------*/
3870 genCmpEq (iCode * ic, iCode * ifx)
3872 operand *left, *right, *result;
3874 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3875 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3876 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3878 /* if literal, literal on the right or
3879 if the right is in a pointer register and left
3881 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3882 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3884 operand *t = IC_RIGHT (ic);
3885 IC_RIGHT (ic) = IC_LEFT (ic);
3889 if (ifx && !AOP_SIZE (result))
3892 /* if they are both bit variables */
3893 if (AOP_TYPE (left) == AOP_CRY &&
3894 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3896 if (AOP_TYPE (right) == AOP_LIT)
3898 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3902 emitcode ("cpl", "c");
3906 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3910 emitcode ("clr", "c");
3912 /* AOP_TYPE(right) == AOP_CRY */
3916 symbol *lbl = newiTempLabel (NULL);
3917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3918 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3919 emitcode ("cpl", "c");
3920 emitcode ("", "%05d$:", (lbl->key + 100));
3922 /* if true label then we jump if condition
3924 tlbl = newiTempLabel (NULL);
3927 emitcode ("jnc", "%05d$", tlbl->key + 100);
3928 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3932 emitcode ("jc", "%05d$", tlbl->key + 100);
3933 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3935 emitcode ("", "%05d$:", tlbl->key + 100);
3939 tlbl = newiTempLabel (NULL);
3940 gencjneshort (left, right, tlbl);
3943 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3944 emitcode ("", "%05d$:", tlbl->key + 100);
3948 symbol *lbl = newiTempLabel (NULL);
3949 emitcode ("sjmp", "%05d$", lbl->key + 100);
3950 emitcode ("", "%05d$:", tlbl->key + 100);
3951 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3952 emitcode ("", "%05d$:", lbl->key + 100);
3955 /* mark the icode as generated */
3960 /* if they are both bit variables */
3961 if (AOP_TYPE (left) == AOP_CRY &&
3962 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3964 if (AOP_TYPE (right) == AOP_LIT)
3966 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3970 emitcode ("cpl", "c");
3974 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3978 emitcode ("clr", "c");
3980 /* AOP_TYPE(right) == AOP_CRY */
3984 symbol *lbl = newiTempLabel (NULL);
3985 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3986 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3987 emitcode ("cpl", "c");
3988 emitcode ("", "%05d$:", (lbl->key + 100));
3991 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3998 genIfxJump (ifx, "c");
4001 /* if the result is used in an arithmetic operation
4002 then put the result in place */
4007 gencjne (left, right, newiTempLabel (NULL));
4008 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4010 aopPut (AOP (result), "a", 0);
4015 genIfxJump (ifx, "a");
4018 /* if the result is used in an arithmetic operation
4019 then put the result in place */
4020 if (AOP_TYPE (result) != AOP_CRY)
4022 /* leave the result in acc */
4026 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4027 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4028 freeAsmop (result, NULL, ic, TRUE);
4031 /*-----------------------------------------------------------------*/
4032 /* ifxForOp - returns the icode containing the ifx for operand */
4033 /*-----------------------------------------------------------------*/
4035 ifxForOp (operand * op, iCode * ic)
4037 /* if true symbol then needs to be assigned */
4038 if (IS_TRUE_SYMOP (op))
4041 /* if this has register type condition and
4042 the next instruction is ifx with the same operand
4043 and live to of the operand is upto the ifx only then */
4045 ic->next->op == IFX &&
4046 IC_COND (ic->next)->key == op->key &&
4047 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4052 /*-----------------------------------------------------------------*/
4053 /* genAndOp - for && operation */
4054 /*-----------------------------------------------------------------*/
4056 genAndOp (iCode * ic)
4058 operand *left, *right, *result;
4061 /* note here that && operations that are in an
4062 if statement are taken away by backPatchLabels
4063 only those used in arthmetic operations remain */
4064 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4065 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4066 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4068 /* if both are bit variables */
4069 if (AOP_TYPE (left) == AOP_CRY &&
4070 AOP_TYPE (right) == AOP_CRY)
4072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4073 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4078 tlbl = newiTempLabel (NULL);
4080 emitcode ("jz", "%05d$", tlbl->key + 100);
4082 emitcode ("", "%05d$:", tlbl->key + 100);
4086 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4087 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4088 freeAsmop (result, NULL, ic, TRUE);
4092 /*-----------------------------------------------------------------*/
4093 /* genOrOp - for || operation */
4094 /*-----------------------------------------------------------------*/
4096 genOrOp (iCode * ic)
4098 operand *left, *right, *result;
4101 /* note here that || operations that are in an
4102 if statement are taken away by backPatchLabels
4103 only those used in arthmetic operations remain */
4104 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4105 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4106 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4108 /* if both are bit variables */
4109 if (AOP_TYPE (left) == AOP_CRY &&
4110 AOP_TYPE (right) == AOP_CRY)
4112 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4113 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4118 tlbl = newiTempLabel (NULL);
4120 emitcode ("jnz", "%05d$", tlbl->key + 100);
4122 emitcode ("", "%05d$:", tlbl->key + 100);
4126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (result, NULL, ic, TRUE);
4131 /*-----------------------------------------------------------------*/
4132 /* isLiteralBit - test if lit == 2^n */
4133 /*-----------------------------------------------------------------*/
4135 isLiteralBit (unsigned long lit)
4137 unsigned long pw[32] =
4138 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4139 0x100L, 0x200L, 0x400L, 0x800L,
4140 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4141 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4142 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4143 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4144 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4147 for (idx = 0; idx < 32; idx++)
4153 /*-----------------------------------------------------------------*/
4154 /* continueIfTrue - */
4155 /*-----------------------------------------------------------------*/
4157 continueIfTrue (iCode * ic)
4160 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4164 /*-----------------------------------------------------------------*/
4166 /*-----------------------------------------------------------------*/
4168 jumpIfTrue (iCode * ic)
4171 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4175 /*-----------------------------------------------------------------*/
4176 /* jmpTrueOrFalse - */
4177 /*-----------------------------------------------------------------*/
4179 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4181 // ugly but optimized by peephole
4184 symbol *nlbl = newiTempLabel (NULL);
4185 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4186 emitcode ("", "%05d$:", tlbl->key + 100);
4187 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4188 emitcode ("", "%05d$:", nlbl->key + 100);
4192 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4193 emitcode ("", "%05d$:", tlbl->key + 100);
4198 /*-----------------------------------------------------------------*/
4199 /* genAnd - code for and */
4200 /*-----------------------------------------------------------------*/
4202 genAnd (iCode * ic, iCode * ifx)
4204 operand *left, *right, *result;
4205 int size, offset = 0;
4206 unsigned long lit = 0L;
4210 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4211 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4212 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4215 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4217 AOP_TYPE (left), AOP_TYPE (right));
4218 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4220 AOP_SIZE (left), AOP_SIZE (right));
4223 /* if left is a literal & right is not then exchange them */
4224 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4225 AOP_NEEDSACC (left))
4227 operand *tmp = right;
4232 /* if result = right then exchange them */
4233 if (sameRegs (AOP (result), AOP (right)))
4235 operand *tmp = right;
4240 /* if right is bit then exchange them */
4241 if (AOP_TYPE (right) == AOP_CRY &&
4242 AOP_TYPE (left) != AOP_CRY)
4244 operand *tmp = right;
4248 if (AOP_TYPE (right) == AOP_LIT)
4249 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4251 size = AOP_SIZE (result);
4254 // result = bit & yy;
4255 if (AOP_TYPE (left) == AOP_CRY)
4257 // c = bit & literal;
4258 if (AOP_TYPE (right) == AOP_LIT)
4262 if (size && sameRegs (AOP (result), AOP (left)))
4265 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4270 if (size && (AOP_TYPE (result) == AOP_CRY))
4272 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4275 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4280 emitcode ("clr", "c");
4285 if (AOP_TYPE (right) == AOP_CRY)
4288 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4289 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4294 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4296 emitcode ("rrc", "a");
4297 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4305 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4306 genIfxJump (ifx, "c");
4310 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4311 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4312 if ((AOP_TYPE (right) == AOP_LIT) &&
4313 (AOP_TYPE (result) == AOP_CRY) &&
4314 (AOP_TYPE (left) != AOP_CRY))
4316 int posbit = isLiteralBit (lit);
4321 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4324 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4330 sprintf (buffer, "acc.%d", posbit & 0x07);
4331 genIfxJump (ifx, buffer);
4338 symbol *tlbl = newiTempLabel (NULL);
4339 int sizel = AOP_SIZE (left);
4341 emitcode ("setb", "c");
4344 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4346 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4348 if ((posbit = isLiteralBit (bytelit)) != 0)
4349 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4352 if (bytelit != 0x0FFL)
4353 emitcode ("anl", "a,%s",
4354 aopGet (AOP (right), offset, FALSE, TRUE));
4355 emitcode ("jnz", "%05d$", tlbl->key + 100);
4360 // bit = left & literal
4363 emitcode ("clr", "c");
4364 emitcode ("", "%05d$:", tlbl->key + 100);
4366 // if(left & literal)
4370 jmpTrueOrFalse (ifx, tlbl);
4378 /* if left is same as result */
4379 if (sameRegs (AOP (result), AOP (left)))
4381 for (; size--; offset++)
4383 if (AOP_TYPE (right) == AOP_LIT)
4385 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4387 else if (bytelit == 0)
4388 aopPut (AOP (result), zero, offset);
4389 else if (IS_AOP_PREG (result))
4391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4392 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4393 aopPut (AOP (result), "a", offset);
4396 emitcode ("anl", "%s,%s",
4397 aopGet (AOP (left), offset, FALSE, TRUE),
4398 aopGet (AOP (right), offset, FALSE, FALSE));
4402 if (AOP_TYPE (left) == AOP_ACC)
4403 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4407 if (IS_AOP_PREG (result))
4409 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4410 aopPut (AOP (result), "a", offset);
4414 emitcode ("anl", "%s,a",
4415 aopGet (AOP (left), offset, FALSE, TRUE));
4422 // left & result in different registers
4423 if (AOP_TYPE (result) == AOP_CRY)
4426 // if(size), result in bit
4427 // if(!size && ifx), conditional oper: if(left & right)
4428 symbol *tlbl = newiTempLabel (NULL);
4429 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4431 emitcode ("setb", "c");
4434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4435 emitcode ("anl", "a,%s",
4436 aopGet (AOP (left), offset, FALSE, FALSE));
4437 emitcode ("jnz", "%05d$", tlbl->key + 100);
4443 emitcode ("", "%05d$:", tlbl->key + 100);
4447 jmpTrueOrFalse (ifx, tlbl);
4451 for (; (size--); offset++)
4454 // result = left & right
4455 if (AOP_TYPE (right) == AOP_LIT)
4457 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4459 aopPut (AOP (result),
4460 aopGet (AOP (left), offset, FALSE, FALSE),
4464 else if (bytelit == 0)
4466 aopPut (AOP (result), zero, offset);
4470 // faster than result <- left, anl result,right
4471 // and better if result is SFR
4472 if (AOP_TYPE (left) == AOP_ACC)
4473 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4476 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4477 emitcode ("anl", "a,%s",
4478 aopGet (AOP (left), offset, FALSE, FALSE));
4480 aopPut (AOP (result), "a", offset);
4486 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4487 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488 freeAsmop (result, NULL, ic, TRUE);
4491 /*-----------------------------------------------------------------*/
4492 /* genOr - code for or */
4493 /*-----------------------------------------------------------------*/
4495 genOr (iCode * ic, iCode * ifx)
4497 operand *left, *right, *result;
4498 int size, offset = 0;
4499 unsigned long lit = 0L;
4501 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4502 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4503 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4506 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4508 AOP_TYPE (left), AOP_TYPE (right));
4509 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4511 AOP_SIZE (left), AOP_SIZE (right));
4514 /* if left is a literal & right is not then exchange them */
4515 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4516 AOP_NEEDSACC (left))
4518 operand *tmp = right;
4523 /* if result = right then exchange them */
4524 if (sameRegs (AOP (result), AOP (right)))
4526 operand *tmp = right;
4531 /* if right is bit then exchange them */
4532 if (AOP_TYPE (right) == AOP_CRY &&
4533 AOP_TYPE (left) != AOP_CRY)
4535 operand *tmp = right;
4539 if (AOP_TYPE (right) == AOP_LIT)
4540 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4542 size = AOP_SIZE (result);
4546 if (AOP_TYPE (left) == AOP_CRY)
4548 if (AOP_TYPE (right) == AOP_LIT)
4550 // c = bit & literal;
4553 // lit != 0 => result = 1
4554 if (AOP_TYPE (result) == AOP_CRY)
4557 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4559 continueIfTrue (ifx);
4562 emitcode ("setb", "c");
4566 // lit == 0 => result = left
4567 if (size && sameRegs (AOP (result), AOP (left)))
4569 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4574 if (AOP_TYPE (right) == AOP_CRY)
4577 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4578 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4583 symbol *tlbl = newiTempLabel (NULL);
4584 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4585 emitcode ("setb", "c");
4586 emitcode ("jb", "%s,%05d$",
4587 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4589 emitcode ("jnz", "%05d$", tlbl->key + 100);
4590 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4592 jmpTrueOrFalse (ifx, tlbl);
4598 emitcode ("", "%05d$:", tlbl->key + 100);
4607 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4608 genIfxJump (ifx, "c");
4612 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4613 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4614 if ((AOP_TYPE (right) == AOP_LIT) &&
4615 (AOP_TYPE (result) == AOP_CRY) &&
4616 (AOP_TYPE (left) != AOP_CRY))
4622 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4624 continueIfTrue (ifx);
4629 // lit = 0, result = boolean(left)
4631 emitcode ("setb", "c");
4635 symbol *tlbl = newiTempLabel (NULL);
4636 emitcode ("jnz", "%05d$", tlbl->key + 100);
4638 emitcode ("", "%05d$:", tlbl->key + 100);
4642 genIfxJump (ifx, "a");
4650 /* if left is same as result */
4651 if (sameRegs (AOP (result), AOP (left)))
4653 for (; size--; offset++)
4655 if (AOP_TYPE (right) == AOP_LIT)
4657 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4659 else if (IS_AOP_PREG (left))
4661 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4662 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4663 aopPut (AOP (result), "a", offset);
4666 emitcode ("orl", "%s,%s",
4667 aopGet (AOP (left), offset, FALSE, TRUE),
4668 aopGet (AOP (right), offset, FALSE, FALSE));
4672 if (AOP_TYPE (left) == AOP_ACC)
4673 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4676 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4677 if (IS_AOP_PREG (left))
4679 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4680 aopPut (AOP (result), "a", offset);
4683 emitcode ("orl", "%s,a",
4684 aopGet (AOP (left), offset, FALSE, TRUE));
4691 // left & result in different registers
4692 if (AOP_TYPE (result) == AOP_CRY)
4695 // if(size), result in bit
4696 // if(!size && ifx), conditional oper: if(left | right)
4697 symbol *tlbl = newiTempLabel (NULL);
4698 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4700 emitcode ("setb", "c");
4703 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4704 emitcode ("orl", "a,%s",
4705 aopGet (AOP (left), offset, FALSE, FALSE));
4706 emitcode ("jnz", "%05d$", tlbl->key + 100);
4712 emitcode ("", "%05d$:", tlbl->key + 100);
4716 jmpTrueOrFalse (ifx, tlbl);
4719 for (; (size--); offset++)
4722 // result = left & right
4723 if (AOP_TYPE (right) == AOP_LIT)
4725 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4727 aopPut (AOP (result),
4728 aopGet (AOP (left), offset, FALSE, FALSE),
4733 // faster than result <- left, anl result,right
4734 // and better if result is SFR
4735 if (AOP_TYPE (left) == AOP_ACC)
4736 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4739 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4740 emitcode ("orl", "a,%s",
4741 aopGet (AOP (left), offset, FALSE, FALSE));
4743 aopPut (AOP (result), "a", offset);
4748 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (result, NULL, ic, TRUE);
4753 /*-----------------------------------------------------------------*/
4754 /* genXor - code for xclusive or */
4755 /*-----------------------------------------------------------------*/
4757 genXor (iCode * ic, iCode * ifx)
4759 operand *left, *right, *result;
4760 int size, offset = 0;
4761 unsigned long lit = 0L;
4763 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4764 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4765 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4768 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4770 AOP_TYPE (left), AOP_TYPE (right));
4771 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4773 AOP_SIZE (left), AOP_SIZE (right));
4776 /* if left is a literal & right is not ||
4777 if left needs acc & right does not */
4778 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4779 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4781 operand *tmp = right;
4786 /* if result = right then exchange them */
4787 if (sameRegs (AOP (result), AOP (right)))
4789 operand *tmp = right;
4794 /* if right is bit then exchange them */
4795 if (AOP_TYPE (right) == AOP_CRY &&
4796 AOP_TYPE (left) != AOP_CRY)
4798 operand *tmp = right;
4802 if (AOP_TYPE (right) == AOP_LIT)
4803 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4805 size = AOP_SIZE (result);
4809 if (AOP_TYPE (left) == AOP_CRY)
4811 if (AOP_TYPE (right) == AOP_LIT)
4813 // c = bit & literal;
4816 // lit>>1 != 0 => result = 1
4817 if (AOP_TYPE (result) == AOP_CRY)
4820 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4822 continueIfTrue (ifx);
4825 emitcode ("setb", "c");
4832 // lit == 0, result = left
4833 if (size && sameRegs (AOP (result), AOP (left)))
4835 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4839 // lit == 1, result = not(left)
4840 if (size && sameRegs (AOP (result), AOP (left)))
4842 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4847 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4848 emitcode ("cpl", "c");
4857 symbol *tlbl = newiTempLabel (NULL);
4858 if (AOP_TYPE (right) == AOP_CRY)
4861 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4865 int sizer = AOP_SIZE (right);
4867 // if val>>1 != 0, result = 1
4868 emitcode ("setb", "c");
4871 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4873 // test the msb of the lsb
4874 emitcode ("anl", "a,#0xfe");
4875 emitcode ("jnz", "%05d$", tlbl->key + 100);
4879 emitcode ("rrc", "a");
4881 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4882 emitcode ("cpl", "c");
4883 emitcode ("", "%05d$:", (tlbl->key + 100));
4890 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4891 genIfxJump (ifx, "c");
4895 if (sameRegs (AOP (result), AOP (left)))
4897 /* if left is same as result */
4898 for (; size--; offset++)
4900 if (AOP_TYPE (right) == AOP_LIT)
4902 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4904 else if (IS_AOP_PREG (left))
4906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4907 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4908 aopPut (AOP (result), "a", offset);
4911 emitcode ("xrl", "%s,%s",
4912 aopGet (AOP (left), offset, FALSE, TRUE),
4913 aopGet (AOP (right), offset, FALSE, FALSE));
4917 if (AOP_TYPE (left) == AOP_ACC)
4918 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4921 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4922 if (IS_AOP_PREG (left))
4924 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4925 aopPut (AOP (result), "a", offset);
4928 emitcode ("xrl", "%s,a",
4929 aopGet (AOP (left), offset, FALSE, TRUE));
4936 // left & result in different registers
4937 if (AOP_TYPE (result) == AOP_CRY)
4940 // if(size), result in bit
4941 // if(!size && ifx), conditional oper: if(left ^ right)
4942 symbol *tlbl = newiTempLabel (NULL);
4943 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4945 emitcode ("setb", "c");
4948 if ((AOP_TYPE (right) == AOP_LIT) &&
4949 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4951 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4955 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4956 emitcode ("xrl", "a,%s",
4957 aopGet (AOP (left), offset, FALSE, FALSE));
4959 emitcode ("jnz", "%05d$", tlbl->key + 100);
4965 emitcode ("", "%05d$:", tlbl->key + 100);
4969 jmpTrueOrFalse (ifx, tlbl);
4972 for (; (size--); offset++)
4975 // result = left & right
4976 if (AOP_TYPE (right) == AOP_LIT)
4978 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4980 aopPut (AOP (result),
4981 aopGet (AOP (left), offset, FALSE, FALSE),
4986 // faster than result <- left, anl result,right
4987 // and better if result is SFR
4988 if (AOP_TYPE (left) == AOP_ACC)
4989 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4992 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4993 emitcode ("xrl", "a,%s",
4994 aopGet (AOP (left), offset, FALSE, TRUE));
4996 aopPut (AOP (result), "a", offset);
5001 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5002 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5003 freeAsmop (result, NULL, ic, TRUE);
5006 /*-----------------------------------------------------------------*/
5007 /* genInline - write the inline code out */
5008 /*-----------------------------------------------------------------*/
5010 genInline (iCode * ic)
5012 char buffer[MAX_INLINEASM];
5016 _G.inLine += (!options.asmpeep);
5017 strcpy (buffer, IC_INLINE (ic));
5019 /* emit each line as a code */
5044 /* emitcode("",buffer); */
5045 _G.inLine -= (!options.asmpeep);
5048 /*-----------------------------------------------------------------*/
5049 /* genRRC - rotate right with carry */
5050 /*-----------------------------------------------------------------*/
5054 operand *left, *result;
5055 int size, offset = 0;
5058 /* rotate right with carry */
5059 left = IC_LEFT (ic);
5060 result = IC_RESULT (ic);
5061 aopOp (left, ic, FALSE);
5062 aopOp (result, ic, FALSE);
5064 /* move it to the result */
5065 size = AOP_SIZE (result);
5070 l = aopGet (AOP (left), offset, FALSE, FALSE);
5072 emitcode ("rrc", "a");
5073 if (AOP_SIZE (result) > 1)
5074 aopPut (AOP (result), "a", offset--);
5076 /* now we need to put the carry into the
5077 highest order byte of the result */
5078 if (AOP_SIZE (result) > 1)
5080 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5083 emitcode ("mov", "acc.7,c");
5084 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5085 freeAsmop (left, NULL, ic, TRUE);
5086 freeAsmop (result, NULL, ic, TRUE);
5089 /*-----------------------------------------------------------------*/
5090 /* genRLC - generate code for rotate left with carry */
5091 /*-----------------------------------------------------------------*/
5095 operand *left, *result;
5096 int size, offset = 0;
5099 /* rotate right with carry */
5100 left = IC_LEFT (ic);
5101 result = IC_RESULT (ic);
5102 aopOp (left, ic, FALSE);
5103 aopOp (result, ic, FALSE);
5105 /* move it to the result */
5106 size = AOP_SIZE (result);
5110 l = aopGet (AOP (left), offset, FALSE, FALSE);
5112 emitcode ("add", "a,acc");
5113 if (AOP_SIZE (result) > 1)
5114 aopPut (AOP (result), "a", offset++);
5117 l = aopGet (AOP (left), offset, FALSE, FALSE);
5119 emitcode ("rlc", "a");
5120 if (AOP_SIZE (result) > 1)
5121 aopPut (AOP (result), "a", offset++);
5124 /* now we need to put the carry into the
5125 highest order byte of the result */
5126 if (AOP_SIZE (result) > 1)
5128 l = aopGet (AOP (result), 0, FALSE, FALSE);
5131 emitcode ("mov", "acc.0,c");
5132 aopPut (AOP (result), "a", 0);
5133 freeAsmop (left, NULL, ic, TRUE);
5134 freeAsmop (result, NULL, ic, TRUE);
5137 /*-----------------------------------------------------------------*/
5138 /* genGetHbit - generates code get highest order bit */
5139 /*-----------------------------------------------------------------*/
5141 genGetHbit (iCode * ic)
5143 operand *left, *result;
5144 left = IC_LEFT (ic);
5145 result = IC_RESULT (ic);
5146 aopOp (left, ic, FALSE);
5147 aopOp (result, ic, FALSE);
5149 /* get the highest order byte into a */
5150 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5151 if (AOP_TYPE (result) == AOP_CRY)
5153 emitcode ("rlc", "a");
5158 emitcode ("rl", "a");
5159 emitcode ("anl", "a,#0x01");
5164 freeAsmop (left, NULL, ic, TRUE);
5165 freeAsmop (result, NULL, ic, TRUE);
5168 /*-----------------------------------------------------------------*/
5169 /* AccRol - rotate left accumulator by known count */
5170 /*-----------------------------------------------------------------*/
5172 AccRol (int shCount)
5174 shCount &= 0x0007; // shCount : 0..7
5181 emitcode ("rl", "a");
5184 emitcode ("rl", "a");
5185 emitcode ("rl", "a");
5188 emitcode ("swap", "a");
5189 emitcode ("rr", "a");
5192 emitcode ("swap", "a");
5195 emitcode ("swap", "a");
5196 emitcode ("rl", "a");
5199 emitcode ("rr", "a");
5200 emitcode ("rr", "a");
5203 emitcode ("rr", "a");
5208 /*-----------------------------------------------------------------*/
5209 /* AccLsh - left shift accumulator by known count */
5210 /*-----------------------------------------------------------------*/
5212 AccLsh (int shCount)
5217 emitcode ("add", "a,acc");
5218 else if (shCount == 2)
5220 emitcode ("add", "a,acc");
5221 emitcode ("add", "a,acc");
5225 /* rotate left accumulator */
5227 /* and kill the lower order bits */
5228 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5233 /*-----------------------------------------------------------------*/
5234 /* AccRsh - right shift accumulator by known count */
5235 /*-----------------------------------------------------------------*/
5237 AccRsh (int shCount)
5244 emitcode ("rrc", "a");
5248 /* rotate right accumulator */
5249 AccRol (8 - shCount);
5250 /* and kill the higher order bits */
5251 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5256 /*-----------------------------------------------------------------*/
5257 /* AccSRsh - signed right shift accumulator by known count */
5258 /*-----------------------------------------------------------------*/
5260 AccSRsh (int shCount)
5267 emitcode ("mov", "c,acc.7");
5268 emitcode ("rrc", "a");
5270 else if (shCount == 2)
5272 emitcode ("mov", "c,acc.7");
5273 emitcode ("rrc", "a");
5274 emitcode ("mov", "c,acc.7");
5275 emitcode ("rrc", "a");
5279 tlbl = newiTempLabel (NULL);
5280 /* rotate right accumulator */
5281 AccRol (8 - shCount);
5282 /* and kill the higher order bits */
5283 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5284 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5285 emitcode ("orl", "a,#0x%02x",
5286 (unsigned char) ~SRMask[shCount]);
5287 emitcode ("", "%05d$:", tlbl->key + 100);
5292 /*-----------------------------------------------------------------*/
5293 /* shiftR1Left2Result - shift right one byte from left to result */
5294 /*-----------------------------------------------------------------*/
5296 shiftR1Left2Result (operand * left, int offl,
5297 operand * result, int offr,
5298 int shCount, int sign)
5300 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5301 /* shift right accumulator */
5306 aopPut (AOP (result), "a", offr);
5309 /*-----------------------------------------------------------------*/
5310 /* shiftL1Left2Result - shift left one byte from left to result */
5311 /*-----------------------------------------------------------------*/
5313 shiftL1Left2Result (operand * left, int offl,
5314 operand * result, int offr, int shCount)
5317 l = aopGet (AOP (left), offl, FALSE, FALSE);
5319 /* shift left accumulator */
5321 aopPut (AOP (result), "a", offr);
5324 /*-----------------------------------------------------------------*/
5325 /* movLeft2Result - move byte from left to result */
5326 /*-----------------------------------------------------------------*/
5328 movLeft2Result (operand * left, int offl,
5329 operand * result, int offr, int sign)
5332 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5334 l = aopGet (AOP (left), offl, FALSE, FALSE);
5336 if (*l == '@' && (IS_AOP_PREG (result)))
5338 emitcode ("mov", "a,%s", l);
5339 aopPut (AOP (result), "a", offr);
5344 aopPut (AOP (result), l, offr);
5347 /* MSB sign in acc.7 ! */
5348 if (getDataSize (left) == offl + 1)
5350 emitcode ("mov", "a,%s", l);
5351 aopPut (AOP (result), "a", offr);
5358 /*-----------------------------------------------------------------*/
5359 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5360 /*-----------------------------------------------------------------*/
5364 emitcode ("rrc", "a");
5365 emitcode ("xch", "a,%s", x);
5366 emitcode ("rrc", "a");
5367 emitcode ("xch", "a,%s", x);
5370 /*-----------------------------------------------------------------*/
5371 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5372 /*-----------------------------------------------------------------*/
5376 emitcode ("xch", "a,%s", x);
5377 emitcode ("rlc", "a");
5378 emitcode ("xch", "a,%s", x);
5379 emitcode ("rlc", "a");
5382 /*-----------------------------------------------------------------*/
5383 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5384 /*-----------------------------------------------------------------*/
5388 emitcode ("xch", "a,%s", x);
5389 emitcode ("add", "a,acc");
5390 emitcode ("xch", "a,%s", x);
5391 emitcode ("rlc", "a");
5394 /*-----------------------------------------------------------------*/
5395 /* AccAXLsh - left shift a:x by known count (0..7) */
5396 /*-----------------------------------------------------------------*/
5398 AccAXLsh (char *x, int shCount)
5413 case 5: // AAAAABBB:CCCCCDDD
5415 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5417 emitcode ("anl", "a,#0x%02x",
5418 SLMask[shCount]); // BBB00000:CCCCCDDD
5420 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5422 AccRol (shCount); // DDDCCCCC:BBB00000
5424 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5426 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5428 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5430 emitcode ("anl", "a,#0x%02x",
5431 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5433 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5435 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5438 case 6: // AAAAAABB:CCCCCCDD
5439 emitcode ("anl", "a,#0x%02x",
5440 SRMask[shCount]); // 000000BB:CCCCCCDD
5441 emitcode ("mov", "c,acc.0"); // c = B
5442 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5444 AccAXRrl1 (x); // BCCCCCCD:D000000B
5445 AccAXRrl1 (x); // BBCCCCCC:DD000000
5447 emitcode("rrc","a");
5448 emitcode("xch","a,%s", x);
5449 emitcode("rrc","a");
5450 emitcode("mov","c,acc.0"); //<< get correct bit
5451 emitcode("xch","a,%s", x);
5453 emitcode("rrc","a");
5454 emitcode("xch","a,%s", x);
5455 emitcode("rrc","a");
5456 emitcode("xch","a,%s", x);
5459 case 7: // a:x <<= 7
5461 emitcode ("anl", "a,#0x%02x",
5462 SRMask[shCount]); // 0000000B:CCCCCCCD
5464 emitcode ("mov", "c,acc.0"); // c = B
5466 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5468 AccAXRrl1 (x); // BCCCCCCC:D0000000
5476 /*-----------------------------------------------------------------*/
5477 /* AccAXRsh - right shift a:x known count (0..7) */
5478 /*-----------------------------------------------------------------*/
5480 AccAXRsh (char *x, int shCount)
5488 AccAXRrl1 (x); // 0->a:x
5493 AccAXRrl1 (x); // 0->a:x
5496 AccAXRrl1 (x); // 0->a:x
5501 case 5: // AAAAABBB:CCCCCDDD = a:x
5503 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5505 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5507 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5509 emitcode ("anl", "a,#0x%02x",
5510 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5512 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5514 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5516 emitcode ("anl", "a,#0x%02x",
5517 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5519 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5521 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5523 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5526 case 6: // AABBBBBB:CCDDDDDD
5528 emitcode ("mov", "c,acc.7");
5529 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5531 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5533 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5535 emitcode ("anl", "a,#0x%02x",
5536 SRMask[shCount]); // 000000AA:BBBBBBCC
5539 case 7: // ABBBBBBB:CDDDDDDD
5541 emitcode ("mov", "c,acc.7"); // c = A
5543 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5545 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5547 emitcode ("anl", "a,#0x%02x",
5548 SRMask[shCount]); // 0000000A:BBBBBBBC
5556 /*-----------------------------------------------------------------*/
5557 /* AccAXRshS - right shift signed a:x known count (0..7) */
5558 /*-----------------------------------------------------------------*/
5560 AccAXRshS (char *x, int shCount)
5568 emitcode ("mov", "c,acc.7");
5569 AccAXRrl1 (x); // s->a:x
5573 emitcode ("mov", "c,acc.7");
5574 AccAXRrl1 (x); // s->a:x
5576 emitcode ("mov", "c,acc.7");
5577 AccAXRrl1 (x); // s->a:x
5582 case 5: // AAAAABBB:CCCCCDDD = a:x
5584 tlbl = newiTempLabel (NULL);
5585 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5587 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5589 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5591 emitcode ("anl", "a,#0x%02x",
5592 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5594 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5596 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5598 emitcode ("anl", "a,#0x%02x",
5599 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5601 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5603 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5605 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5607 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5608 emitcode ("orl", "a,#0x%02x",
5609 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5611 emitcode ("", "%05d$:", tlbl->key + 100);
5612 break; // SSSSAAAA:BBBCCCCC
5614 case 6: // AABBBBBB:CCDDDDDD
5616 tlbl = newiTempLabel (NULL);
5617 emitcode ("mov", "c,acc.7");
5618 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5620 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5622 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5624 emitcode ("anl", "a,#0x%02x",
5625 SRMask[shCount]); // 000000AA:BBBBBBCC
5627 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5628 emitcode ("orl", "a,#0x%02x",
5629 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5631 emitcode ("", "%05d$:", tlbl->key + 100);
5633 case 7: // ABBBBBBB:CDDDDDDD
5635 tlbl = newiTempLabel (NULL);
5636 emitcode ("mov", "c,acc.7"); // c = A
5638 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5640 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5642 emitcode ("anl", "a,#0x%02x",
5643 SRMask[shCount]); // 0000000A:BBBBBBBC
5645 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5646 emitcode ("orl", "a,#0x%02x",
5647 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5649 emitcode ("", "%05d$:", tlbl->key + 100);
5656 /*-----------------------------------------------------------------*/
5657 /* shiftL2Left2Result - shift left two bytes from left to result */
5658 /*-----------------------------------------------------------------*/
5660 shiftL2Left2Result (operand * left, int offl,
5661 operand * result, int offr, int shCount)
5663 if (sameRegs (AOP (result), AOP (left)) &&
5664 ((offl + MSB16) == offr))
5666 /* don't crash result[offr] */
5667 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5668 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5672 movLeft2Result (left, offl, result, offr, 0);
5673 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5675 /* ax << shCount (x = lsb(result)) */
5676 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5677 aopPut (AOP (result), "a", offr + MSB16);
5681 /*-----------------------------------------------------------------*/
5682 /* shiftR2Left2Result - shift right two bytes from left to result */
5683 /*-----------------------------------------------------------------*/
5685 shiftR2Left2Result (operand * left, int offl,
5686 operand * result, int offr,
5687 int shCount, int sign)
5689 if (sameRegs (AOP (result), AOP (left)) &&
5690 ((offl + MSB16) == offr))
5692 /* don't crash result[offr] */
5693 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5694 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5698 movLeft2Result (left, offl, result, offr, 0);
5699 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5701 /* a:x >> shCount (x = lsb(result)) */
5703 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5705 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5706 if (getDataSize (result) > 1)
5707 aopPut (AOP (result), "a", offr + MSB16);
5710 /*-----------------------------------------------------------------*/
5711 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5712 /*-----------------------------------------------------------------*/
5714 shiftLLeftOrResult (operand * left, int offl,
5715 operand * result, int offr, int shCount)
5717 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5718 /* shift left accumulator */
5720 /* or with result */
5721 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5722 /* back to result */
5723 aopPut (AOP (result), "a", offr);
5726 /*-----------------------------------------------------------------*/
5727 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5728 /*-----------------------------------------------------------------*/
5730 shiftRLeftOrResult (operand * left, int offl,
5731 operand * result, int offr, int shCount)
5733 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5734 /* shift right accumulator */
5736 /* or with result */
5737 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5738 /* back to result */
5739 aopPut (AOP (result), "a", offr);
5742 /*-----------------------------------------------------------------*/
5743 /* genlshOne - left shift a one byte quantity by known count */
5744 /*-----------------------------------------------------------------*/
5746 genlshOne (operand * result, operand * left, int shCount)
5748 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5751 /*-----------------------------------------------------------------*/
5752 /* genlshTwo - left shift two bytes by known amount != 0 */
5753 /*-----------------------------------------------------------------*/
5755 genlshTwo (operand * result, operand * left, int shCount)
5759 size = getDataSize (result);
5761 /* if shCount >= 8 */
5769 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5771 movLeft2Result (left, LSB, result, MSB16, 0);
5773 aopPut (AOP (result), zero, LSB);
5776 /* 1 <= shCount <= 7 */
5780 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5782 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5786 /*-----------------------------------------------------------------*/
5787 /* shiftLLong - shift left one long from left to result */
5788 /* offl = LSB or MSB16 */
5789 /*-----------------------------------------------------------------*/
5791 shiftLLong (operand * left, operand * result, int offr)
5794 int size = AOP_SIZE (result);
5796 if (size >= LSB + offr)
5798 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5800 emitcode ("add", "a,acc");
5801 if (sameRegs (AOP (left), AOP (result)) &&
5802 size >= MSB16 + offr && offr != LSB)
5803 emitcode ("xch", "a,%s",
5804 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5806 aopPut (AOP (result), "a", LSB + offr);
5809 if (size >= MSB16 + offr)
5811 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5813 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5816 emitcode ("rlc", "a");
5817 if (sameRegs (AOP (left), AOP (result)) &&
5818 size >= MSB24 + offr && offr != LSB)
5819 emitcode ("xch", "a,%s",
5820 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5822 aopPut (AOP (result), "a", MSB16 + offr);
5825 if (size >= MSB24 + offr)
5827 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5829 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5832 emitcode ("rlc", "a");
5833 if (sameRegs (AOP (left), AOP (result)) &&
5834 size >= MSB32 + offr && offr != LSB)
5835 emitcode ("xch", "a,%s",
5836 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5838 aopPut (AOP (result), "a", MSB24 + offr);
5841 if (size > MSB32 + offr)
5843 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5845 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5848 emitcode ("rlc", "a");
5849 aopPut (AOP (result), "a", MSB32 + offr);
5852 aopPut (AOP (result), zero, LSB);
5855 /*-----------------------------------------------------------------*/
5856 /* genlshFour - shift four byte by a known amount != 0 */
5857 /*-----------------------------------------------------------------*/
5859 genlshFour (operand * result, operand * left, int shCount)
5863 size = AOP_SIZE (result);
5865 /* if shifting more that 3 bytes */
5870 /* lowest order of left goes to the highest
5871 order of the destination */
5872 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5874 movLeft2Result (left, LSB, result, MSB32, 0);
5875 aopPut (AOP (result), zero, LSB);
5876 aopPut (AOP (result), zero, MSB16);
5877 aopPut (AOP (result), zero, MSB32);
5881 /* more than two bytes */
5882 else if (shCount >= 16)
5884 /* lower order two bytes goes to higher order two bytes */
5886 /* if some more remaining */
5888 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5891 movLeft2Result (left, MSB16, result, MSB32, 0);
5892 movLeft2Result (left, LSB, result, MSB24, 0);
5894 aopPut (AOP (result), zero, MSB16);
5895 aopPut (AOP (result), zero, LSB);
5899 /* if more than 1 byte */
5900 else if (shCount >= 8)
5902 /* lower order three bytes goes to higher order three bytes */
5907 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5909 movLeft2Result (left, LSB, result, MSB16, 0);
5915 movLeft2Result (left, MSB24, result, MSB32, 0);
5916 movLeft2Result (left, MSB16, result, MSB24, 0);
5917 movLeft2Result (left, LSB, result, MSB16, 0);
5918 aopPut (AOP (result), zero, LSB);
5920 else if (shCount == 1)
5921 shiftLLong (left, result, MSB16);
5924 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5925 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5926 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5927 aopPut (AOP (result), zero, LSB);
5932 /* 1 <= shCount <= 7 */
5933 else if (shCount <= 2)
5935 shiftLLong (left, result, LSB);
5937 shiftLLong (result, result, LSB);
5939 /* 3 <= shCount <= 7, optimize */
5942 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5943 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5944 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5948 /*-----------------------------------------------------------------*/
5949 /* genLeftShiftLiteral - left shifting by known count */
5950 /*-----------------------------------------------------------------*/
5952 genLeftShiftLiteral (operand * left,
5957 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5960 freeAsmop (right, NULL, ic, TRUE);
5962 aopOp (left, ic, FALSE);
5963 aopOp (result, ic, FALSE);
5965 size = getSize (operandType (result));
5968 emitcode ("; shift left ", "result %d, left %d", size,
5972 /* I suppose that the left size >= result size */
5977 movLeft2Result (left, size, result, size, 0);
5981 else if (shCount >= (size * 8))
5983 aopPut (AOP (result), zero, size);
5989 genlshOne (result, left, shCount);
5994 genlshTwo (result, left, shCount);
5998 genlshFour (result, left, shCount);
6002 freeAsmop (left, NULL, ic, TRUE);
6003 freeAsmop (result, NULL, ic, TRUE);
6006 /*-----------------------------------------------------------------*/
6007 /* genLeftShift - generates code for left shifting */
6008 /*-----------------------------------------------------------------*/
6010 genLeftShift (iCode * ic)
6012 operand *left, *right, *result;
6015 symbol *tlbl, *tlbl1;
6017 right = IC_RIGHT (ic);
6018 left = IC_LEFT (ic);
6019 result = IC_RESULT (ic);
6021 aopOp (right, ic, FALSE);
6023 /* if the shift count is known then do it
6024 as efficiently as possible */
6025 if (AOP_TYPE (right) == AOP_LIT)
6027 genLeftShiftLiteral (left, right, result, ic);
6031 /* shift count is unknown then we have to form
6032 a loop get the loop count in B : Note: we take
6033 only the lower order byte since shifting
6034 more that 32 bits make no sense anyway, ( the
6035 largest size of an object can be only 32 bits ) */
6037 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6038 emitcode ("inc", "b");
6039 freeAsmop (right, NULL, ic, TRUE);
6040 aopOp (left, ic, FALSE);
6041 aopOp (result, ic, FALSE);
6043 /* now move the left to the result if they are not the
6045 if (!sameRegs (AOP (left), AOP (result)) &&
6046 AOP_SIZE (result) > 1)
6049 size = AOP_SIZE (result);
6053 l = aopGet (AOP (left), offset, FALSE, TRUE);
6054 if (*l == '@' && (IS_AOP_PREG (result)))
6057 emitcode ("mov", "a,%s", l);
6058 aopPut (AOP (result), "a", offset);
6061 aopPut (AOP (result), l, offset);
6066 tlbl = newiTempLabel (NULL);
6067 size = AOP_SIZE (result);
6069 tlbl1 = newiTempLabel (NULL);
6071 /* if it is only one byte then */
6074 symbol *tlbl1 = newiTempLabel (NULL);
6076 l = aopGet (AOP (left), 0, FALSE, FALSE);
6078 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6079 emitcode ("", "%05d$:", tlbl->key + 100);
6080 emitcode ("add", "a,acc");
6081 emitcode ("", "%05d$:", tlbl1->key + 100);
6082 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6083 aopPut (AOP (result), "a", 0);
6087 reAdjustPreg (AOP (result));
6089 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6090 emitcode ("", "%05d$:", tlbl->key + 100);
6091 l = aopGet (AOP (result), offset, FALSE, FALSE);
6093 emitcode ("add", "a,acc");
6094 aopPut (AOP (result), "a", offset++);
6097 l = aopGet (AOP (result), offset, FALSE, FALSE);
6099 emitcode ("rlc", "a");
6100 aopPut (AOP (result), "a", offset++);
6102 reAdjustPreg (AOP (result));
6104 emitcode ("", "%05d$:", tlbl1->key + 100);
6105 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6107 freeAsmop (left, NULL, ic, TRUE);
6108 freeAsmop (result, NULL, ic, TRUE);
6111 /*-----------------------------------------------------------------*/
6112 /* genrshOne - right shift a one byte quantity by known count */
6113 /*-----------------------------------------------------------------*/
6115 genrshOne (operand * result, operand * left,
6116 int shCount, int sign)
6118 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6121 /*-----------------------------------------------------------------*/
6122 /* genrshTwo - right shift two bytes by known amount != 0 */
6123 /*-----------------------------------------------------------------*/
6125 genrshTwo (operand * result, operand * left,
6126 int shCount, int sign)
6128 /* if shCount >= 8 */
6133 shiftR1Left2Result (left, MSB16, result, LSB,
6136 movLeft2Result (left, MSB16, result, LSB, sign);
6137 addSign (result, MSB16, sign);
6140 /* 1 <= shCount <= 7 */
6142 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6145 /*-----------------------------------------------------------------*/
6146 /* shiftRLong - shift right one long from left to result */
6147 /* offl = LSB or MSB16 */
6148 /*-----------------------------------------------------------------*/
6150 shiftRLong (operand * left, int offl,
6151 operand * result, int sign)
6154 emitcode ("clr", "c");
6155 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6157 emitcode ("mov", "c,acc.7");
6158 emitcode ("rrc", "a");
6159 aopPut (AOP (result), "a", MSB32 - offl);
6161 /* add sign of "a" */
6162 addSign (result, MSB32, sign);
6164 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6165 emitcode ("rrc", "a");
6166 aopPut (AOP (result), "a", MSB24 - offl);
6168 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6169 emitcode ("rrc", "a");
6170 aopPut (AOP (result), "a", MSB16 - offl);
6174 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6175 emitcode ("rrc", "a");
6176 aopPut (AOP (result), "a", LSB);
6180 /*-----------------------------------------------------------------*/
6181 /* genrshFour - shift four byte by a known amount != 0 */
6182 /*-----------------------------------------------------------------*/
6184 genrshFour (operand * result, operand * left,
6185 int shCount, int sign)
6187 /* if shifting more that 3 bytes */
6192 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6194 movLeft2Result (left, MSB32, result, LSB, sign);
6195 addSign (result, MSB16, sign);
6197 else if (shCount >= 16)
6201 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6204 movLeft2Result (left, MSB24, result, LSB, 0);
6205 movLeft2Result (left, MSB32, result, MSB16, sign);
6207 addSign (result, MSB24, sign);
6209 else if (shCount >= 8)
6213 shiftRLong (left, MSB16, result, sign);
6214 else if (shCount == 0)
6216 movLeft2Result (left, MSB16, result, LSB, 0);
6217 movLeft2Result (left, MSB24, result, MSB16, 0);
6218 movLeft2Result (left, MSB32, result, MSB24, sign);
6219 addSign (result, MSB32, sign);
6223 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6224 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6225 /* the last shift is signed */
6226 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6227 addSign (result, MSB32, sign);
6231 { /* 1 <= shCount <= 7 */
6234 shiftRLong (left, LSB, result, sign);
6236 shiftRLong (result, LSB, result, sign);
6240 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6241 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6242 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6247 /*-----------------------------------------------------------------*/
6248 /* genRightShiftLiteral - right shifting by known count */
6249 /*-----------------------------------------------------------------*/
6251 genRightShiftLiteral (operand * left,
6257 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6260 freeAsmop (right, NULL, ic, TRUE);
6262 aopOp (left, ic, FALSE);
6263 aopOp (result, ic, FALSE);
6266 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6270 size = getDataSize (left);
6271 /* test the LEFT size !!! */
6273 /* I suppose that the left size >= result size */
6276 size = getDataSize (result);
6278 movLeft2Result (left, size, result, size, 0);
6281 else if (shCount >= (size * 8))
6284 /* get sign in acc.7 */
6285 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6286 addSign (result, LSB, sign);
6293 genrshOne (result, left, shCount, sign);
6297 genrshTwo (result, left, shCount, sign);
6301 genrshFour (result, left, shCount, sign);
6307 freeAsmop (left, NULL, ic, TRUE);
6308 freeAsmop (result, NULL, ic, TRUE);
6312 /*-----------------------------------------------------------------*/
6313 /* genSignedRightShift - right shift of signed number */
6314 /*-----------------------------------------------------------------*/
6316 genSignedRightShift (iCode * ic)
6318 operand *right, *left, *result;
6321 symbol *tlbl, *tlbl1;
6323 /* we do it the hard way put the shift count in b
6324 and loop thru preserving the sign */
6326 right = IC_RIGHT (ic);
6327 left = IC_LEFT (ic);
6328 result = IC_RESULT (ic);
6330 aopOp (right, ic, FALSE);
6333 if (AOP_TYPE (right) == AOP_LIT)
6335 genRightShiftLiteral (left, right, result, ic, 1);
6338 /* shift count is unknown then we have to form
6339 a loop get the loop count in B : Note: we take
6340 only the lower order byte since shifting
6341 more that 32 bits make no sense anyway, ( the
6342 largest size of an object can be only 32 bits ) */
6344 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6345 emitcode ("inc", "b");
6346 freeAsmop (right, NULL, ic, TRUE);
6347 aopOp (left, ic, FALSE);
6348 aopOp (result, ic, FALSE);
6350 /* now move the left to the result if they are not the
6352 if (!sameRegs (AOP (left), AOP (result)) &&
6353 AOP_SIZE (result) > 1)
6356 size = AOP_SIZE (result);
6360 l = aopGet (AOP (left), offset, FALSE, TRUE);
6361 if (*l == '@' && IS_AOP_PREG (result))
6364 emitcode ("mov", "a,%s", l);
6365 aopPut (AOP (result), "a", offset);
6368 aopPut (AOP (result), l, offset);
6373 /* mov the highest order bit to OVR */
6374 tlbl = newiTempLabel (NULL);
6375 tlbl1 = newiTempLabel (NULL);
6377 size = AOP_SIZE (result);
6379 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6380 emitcode ("rlc", "a");
6381 emitcode ("mov", "ov,c");
6382 /* if it is only one byte then */
6385 l = aopGet (AOP (left), 0, FALSE, FALSE);
6387 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6388 emitcode ("", "%05d$:", tlbl->key + 100);
6389 emitcode ("mov", "c,ov");
6390 emitcode ("rrc", "a");
6391 emitcode ("", "%05d$:", tlbl1->key + 100);
6392 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6393 aopPut (AOP (result), "a", 0);
6397 reAdjustPreg (AOP (result));
6398 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6399 emitcode ("", "%05d$:", tlbl->key + 100);
6400 emitcode ("mov", "c,ov");
6403 l = aopGet (AOP (result), offset, FALSE, FALSE);
6405 emitcode ("rrc", "a");
6406 aopPut (AOP (result), "a", offset--);
6408 reAdjustPreg (AOP (result));
6409 emitcode ("", "%05d$:", tlbl1->key + 100);
6410 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6413 freeAsmop (left, NULL, ic, TRUE);
6414 freeAsmop (result, NULL, ic, TRUE);
6417 /*-----------------------------------------------------------------*/
6418 /* genRightShift - generate code for right shifting */
6419 /*-----------------------------------------------------------------*/
6421 genRightShift (iCode * ic)
6423 operand *right, *left, *result;
6427 symbol *tlbl, *tlbl1;
6429 /* if signed then we do it the hard way preserve the
6430 sign bit moving it inwards */
6431 retype = getSpec (operandType (IC_RESULT (ic)));
6433 if (!SPEC_USIGN (retype))
6435 genSignedRightShift (ic);
6439 /* signed & unsigned types are treated the same : i.e. the
6440 signed is NOT propagated inwards : quoting from the
6441 ANSI - standard : "for E1 >> E2, is equivalent to division
6442 by 2**E2 if unsigned or if it has a non-negative value,
6443 otherwise the result is implementation defined ", MY definition
6444 is that the sign does not get propagated */
6446 right = IC_RIGHT (ic);
6447 left = IC_LEFT (ic);
6448 result = IC_RESULT (ic);
6450 aopOp (right, ic, FALSE);
6452 /* if the shift count is known then do it
6453 as efficiently as possible */
6454 if (AOP_TYPE (right) == AOP_LIT)
6456 genRightShiftLiteral (left, right, result, ic, 0);
6460 /* shift count is unknown then we have to form
6461 a loop get the loop count in B : Note: we take
6462 only the lower order byte since shifting
6463 more that 32 bits make no sense anyway, ( the
6464 largest size of an object can be only 32 bits ) */
6466 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6467 emitcode ("inc", "b");
6468 freeAsmop (right, NULL, ic, TRUE);
6469 aopOp (left, ic, FALSE);
6470 aopOp (result, ic, FALSE);
6472 /* now move the left to the result if they are not the
6474 if (!sameRegs (AOP (left), AOP (result)) &&
6475 AOP_SIZE (result) > 1)
6478 size = AOP_SIZE (result);
6482 l = aopGet (AOP (left), offset, FALSE, TRUE);
6483 if (*l == '@' && IS_AOP_PREG (result))
6486 emitcode ("mov", "a,%s", l);
6487 aopPut (AOP (result), "a", offset);
6490 aopPut (AOP (result), l, offset);
6495 tlbl = newiTempLabel (NULL);
6496 tlbl1 = newiTempLabel (NULL);
6497 size = AOP_SIZE (result);
6500 /* if it is only one byte then */
6503 l = aopGet (AOP (left), 0, FALSE, FALSE);
6505 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6506 emitcode ("", "%05d$:", tlbl->key + 100);
6508 emitcode ("rrc", "a");
6509 emitcode ("", "%05d$:", tlbl1->key + 100);
6510 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6511 aopPut (AOP (result), "a", 0);
6515 reAdjustPreg (AOP (result));
6516 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6517 emitcode ("", "%05d$:", tlbl->key + 100);
6521 l = aopGet (AOP (result), offset, FALSE, FALSE);
6523 emitcode ("rrc", "a");
6524 aopPut (AOP (result), "a", offset--);
6526 reAdjustPreg (AOP (result));
6528 emitcode ("", "%05d$:", tlbl1->key + 100);
6529 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6532 freeAsmop (left, NULL, ic, TRUE);
6533 freeAsmop (result, NULL, ic, TRUE);
6536 /*-----------------------------------------------------------------*/
6537 /* genUnpackBits - generates code for unpacking bits */
6538 /*-----------------------------------------------------------------*/
6540 genUnpackBits (operand * result, char *rname, int ptype)
6548 etype = getSpec (operandType (result));
6549 rsize = getSize (operandType (result));
6550 /* read the first byte */
6556 emitcode ("mov", "a,@%s", rname);
6560 emitcode ("movx", "a,@%s", rname);
6564 emitcode ("movx", "a,@dptr");
6568 emitcode ("clr", "a");
6569 emitcode ("movc", "a,%s", "@a+dptr");
6573 emitcode ("lcall", "__gptrget");
6577 rlen = SPEC_BLEN (etype);
6579 /* if we have bitdisplacement then it fits */
6580 /* into this byte completely or if length is */
6581 /* less than a byte */
6582 if ((shCnt = SPEC_BSTR (etype)) ||
6583 (SPEC_BLEN (etype) <= 8))
6586 /* shift right acc */
6589 emitcode ("anl", "a,#0x%02x",
6590 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6591 aopPut (AOP (result), "a", offset++);
6595 /* bit field did not fit in a byte */
6596 aopPut (AOP (result), "a", offset++);
6605 emitcode ("inc", "%s", rname);
6606 emitcode ("mov", "a,@%s", rname);
6610 emitcode ("inc", "%s", rname);
6611 emitcode ("movx", "a,@%s", rname);
6615 emitcode ("inc", "dptr");
6616 emitcode ("movx", "a,@dptr");
6620 emitcode ("clr", "a");
6621 emitcode ("inc", "dptr");
6622 emitcode ("movc", "a", "@a+dptr");
6626 emitcode ("inc", "dptr");
6627 emitcode ("lcall", "__gptrget");
6632 /* if we are done */
6636 aopPut (AOP (result), "a", offset++);
6642 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6644 aopPut (AOP (result), "a", offset++);
6652 aopPut (AOP (result), zero, offset++);
6658 /*-----------------------------------------------------------------*/
6659 /* genDataPointerGet - generates code when ptr offset is known */
6660 /*-----------------------------------------------------------------*/
6662 genDataPointerGet (operand * left,
6668 int size, offset = 0;
6669 aopOp (result, ic, TRUE);
6671 /* get the string representation of the name */
6672 l = aopGet (AOP (left), 0, FALSE, TRUE);
6673 size = AOP_SIZE (result);
6677 sprintf (buffer, "(%s + %d)", l + 1, offset);
6679 sprintf (buffer, "%s", l + 1);
6680 aopPut (AOP (result), buffer, offset++);
6683 freeAsmop (left, NULL, ic, TRUE);
6684 freeAsmop (result, NULL, ic, TRUE);
6687 /*-----------------------------------------------------------------*/
6688 /* genNearPointerGet - emitcode for near pointer fetch */
6689 /*-----------------------------------------------------------------*/
6691 genNearPointerGet (operand * left,
6698 sym_link *rtype, *retype;
6699 sym_link *ltype = operandType (left);
6702 rtype = operandType (result);
6703 retype = getSpec (rtype);
6705 aopOp (left, ic, FALSE);
6707 /* if left is rematerialisable and
6708 result is not bit variable type and
6709 the left is pointer to data space i.e
6710 lower 128 bytes of space */
6711 if (AOP_TYPE (left) == AOP_IMMD &&
6712 !IS_BITVAR (retype) &&
6713 DCL_TYPE (ltype) == POINTER)
6715 genDataPointerGet (left, result, ic);
6719 /* if the value is already in a pointer register
6720 then don't need anything more */
6721 if (!AOP_INPREG (AOP (left)))
6723 /* otherwise get a free pointer register */
6725 preg = getFreePtr (ic, &aop, FALSE);
6726 emitcode ("mov", "%s,%s",
6728 aopGet (AOP (left), 0, FALSE, TRUE));
6732 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6734 freeAsmop (left, NULL, ic, TRUE);
6735 aopOp (result, ic, FALSE);
6737 /* if bitfield then unpack the bits */
6738 if (IS_BITVAR (retype))
6739 genUnpackBits (result, rname, POINTER);
6742 /* we have can just get the values */
6743 int size = AOP_SIZE (result);
6748 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6751 emitcode ("mov", "a,@%s", rname);
6752 aopPut (AOP (result), "a", offset);
6756 sprintf (buffer, "@%s", rname);
6757 aopPut (AOP (result), buffer, offset);
6761 emitcode ("inc", "%s", rname);
6765 /* now some housekeeping stuff */
6768 /* we had to allocate for this iCode */
6769 freeAsmop (NULL, aop, ic, TRUE);
6773 /* we did not allocate which means left
6774 already in a pointer register, then
6775 if size > 0 && this could be used again
6776 we have to point it back to where it
6778 if (AOP_SIZE (result) > 1 &&
6779 !OP_SYMBOL (left)->remat &&
6780 (OP_SYMBOL (left)->liveTo > ic->seq ||
6783 int size = AOP_SIZE (result) - 1;
6785 emitcode ("dec", "%s", rname);
6790 freeAsmop (result, NULL, ic, TRUE);
6794 /*-----------------------------------------------------------------*/
6795 /* genPagedPointerGet - emitcode for paged pointer fetch */
6796 /*-----------------------------------------------------------------*/
6798 genPagedPointerGet (operand * left,
6805 sym_link *rtype, *retype;
6807 rtype = operandType (result);
6808 retype = getSpec (rtype);
6810 aopOp (left, ic, FALSE);
6812 /* if the value is already in a pointer register
6813 then don't need anything more */
6814 if (!AOP_INPREG (AOP (left)))
6816 /* otherwise get a free pointer register */
6818 preg = getFreePtr (ic, &aop, FALSE);
6819 emitcode ("mov", "%s,%s",
6821 aopGet (AOP (left), 0, FALSE, TRUE));
6825 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6827 freeAsmop (left, NULL, ic, TRUE);
6828 aopOp (result, ic, FALSE);
6830 /* if bitfield then unpack the bits */
6831 if (IS_BITVAR (retype))
6832 genUnpackBits (result, rname, PPOINTER);
6835 /* we have can just get the values */
6836 int size = AOP_SIZE (result);
6842 emitcode ("movx", "a,@%s", rname);
6843 aopPut (AOP (result), "a", offset);
6848 emitcode ("inc", "%s", rname);
6852 /* now some housekeeping stuff */
6855 /* we had to allocate for this iCode */
6856 freeAsmop (NULL, aop, ic, TRUE);
6860 /* we did not allocate which means left
6861 already in a pointer register, then
6862 if size > 0 && this could be used again
6863 we have to point it back to where it
6865 if (AOP_SIZE (result) > 1 &&
6866 !OP_SYMBOL (left)->remat &&
6867 (OP_SYMBOL (left)->liveTo > ic->seq ||
6870 int size = AOP_SIZE (result) - 1;
6872 emitcode ("dec", "%s", rname);
6877 freeAsmop (result, NULL, ic, TRUE);
6882 /*-----------------------------------------------------------------*/
6883 /* genFarPointerGet - gget value from far space */
6884 /*-----------------------------------------------------------------*/
6886 genFarPointerGet (operand * left,
6887 operand * result, iCode * ic)
6890 sym_link *retype = getSpec (operandType (result));
6892 aopOp (left, ic, FALSE);
6894 /* if the operand is already in dptr
6895 then we do nothing else we move the value to dptr */
6896 if (AOP_TYPE (left) != AOP_STR)
6898 /* if this is remateriazable */
6899 if (AOP_TYPE (left) == AOP_IMMD)
6900 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6902 { /* we need to get it byte by byte */
6903 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6904 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6907 /* so dptr know contains the address */
6908 freeAsmop (left, NULL, ic, TRUE);
6909 aopOp (result, ic, FALSE);
6911 /* if bit then unpack */
6912 if (IS_BITVAR (retype))
6913 genUnpackBits (result, "dptr", FPOINTER);
6916 size = AOP_SIZE (result);
6921 emitcode ("movx", "a,@dptr");
6922 aopPut (AOP (result), "a", offset++);
6924 emitcode ("inc", "dptr");
6928 freeAsmop (result, NULL, ic, TRUE);
6931 /*-----------------------------------------------------------------*/
6932 /* emitcodePointerGet - gget value from code space */
6933 /*-----------------------------------------------------------------*/
6935 emitcodePointerGet (operand * left,
6936 operand * result, iCode * ic)
6939 sym_link *retype = getSpec (operandType (result));
6941 aopOp (left, ic, FALSE);
6943 /* if the operand is already in dptr
6944 then we do nothing else we move the value to dptr */
6945 if (AOP_TYPE (left) != AOP_STR)
6947 /* if this is remateriazable */
6948 if (AOP_TYPE (left) == AOP_IMMD)
6949 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6951 { /* we need to get it byte by byte */
6952 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6953 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6956 /* so dptr know contains the address */
6957 freeAsmop (left, NULL, ic, TRUE);
6958 aopOp (result, ic, FALSE);
6960 /* if bit then unpack */
6961 if (IS_BITVAR (retype))
6962 genUnpackBits (result, "dptr", CPOINTER);
6965 size = AOP_SIZE (result);
6970 emitcode ("clr", "a");
6971 emitcode ("movc", "a,@a+dptr");
6972 aopPut (AOP (result), "a", offset++);
6974 emitcode ("inc", "dptr");
6978 freeAsmop (result, NULL, ic, TRUE);
6981 /*-----------------------------------------------------------------*/
6982 /* genGenPointerGet - gget value from generic pointer space */
6983 /*-----------------------------------------------------------------*/
6985 genGenPointerGet (operand * left,
6986 operand * result, iCode * ic)
6989 sym_link *retype = getSpec (operandType (result));
6991 aopOp (left, ic, FALSE);
6993 /* if the operand is already in dptr
6994 then we do nothing else we move the value to dptr */
6995 if (AOP_TYPE (left) != AOP_STR)
6997 /* if this is remateriazable */
6998 if (AOP_TYPE (left) == AOP_IMMD)
7000 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7001 emitcode ("mov", "b,#%d", pointerCode (retype));
7004 { /* we need to get it byte by byte */
7005 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7006 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7007 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7010 /* so dptr know contains the address */
7011 freeAsmop (left, NULL, ic, TRUE);
7012 aopOp (result, ic, FALSE);
7014 /* if bit then unpack */
7015 if (IS_BITVAR (retype))
7016 genUnpackBits (result, "dptr", GPOINTER);
7019 size = AOP_SIZE (result);
7024 emitcode ("lcall", "__gptrget");
7025 aopPut (AOP (result), "a", offset++);
7027 emitcode ("inc", "dptr");
7031 freeAsmop (result, NULL, ic, TRUE);
7034 /*-----------------------------------------------------------------*/
7035 /* genPointerGet - generate code for pointer get */
7036 /*-----------------------------------------------------------------*/
7038 genPointerGet (iCode * ic)
7040 operand *left, *result;
7041 sym_link *type, *etype;
7044 left = IC_LEFT (ic);
7045 result = IC_RESULT (ic);
7047 /* depending on the type of pointer we need to
7048 move it to the correct pointer register */
7049 type = operandType (left);
7050 etype = getSpec (type);
7051 /* if left is of type of pointer then it is simple */
7052 if (IS_PTR (type) && !IS_FUNC (type->next))
7053 p_type = DCL_TYPE (type);
7056 /* we have to go by the storage class */
7057 p_type = PTR_TYPE (SPEC_OCLS (etype));
7059 /* if (SPEC_OCLS(etype)->codesp ) { */
7060 /* p_type = CPOINTER ; */
7063 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7064 /* p_type = FPOINTER ; */
7066 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7067 /* p_type = PPOINTER; */
7069 /* if (SPEC_OCLS(etype) == idata ) */
7070 /* p_type = IPOINTER; */
7072 /* p_type = POINTER ; */
7075 /* now that we have the pointer type we assign
7076 the pointer values */
7082 genNearPointerGet (left, result, ic);
7086 genPagedPointerGet (left, result, ic);
7090 genFarPointerGet (left, result, ic);
7094 emitcodePointerGet (left, result, ic);
7098 genGenPointerGet (left, result, ic);
7104 /*-----------------------------------------------------------------*/
7105 /* genPackBits - generates code for packed bit storage */
7106 /*-----------------------------------------------------------------*/
7108 genPackBits (sym_link * etype,
7110 char *rname, int p_type)
7118 blen = SPEC_BLEN (etype);
7119 bstr = SPEC_BSTR (etype);
7121 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7124 /* if the bit lenth is less than or */
7125 /* it exactly fits a byte then */
7126 if (SPEC_BLEN (etype) <= 8)
7128 shCount = SPEC_BSTR (etype);
7130 /* shift left acc */
7133 if (SPEC_BLEN (etype) < 8)
7134 { /* if smaller than a byte */
7140 emitcode ("mov", "b,a");
7141 emitcode ("mov", "a,@%s", rname);
7145 emitcode ("mov", "b,a");
7146 emitcode ("movx", "a,@dptr");
7150 emitcode ("push", "b");
7151 emitcode ("push", "acc");
7152 emitcode ("lcall", "__gptrget");
7153 emitcode ("pop", "b");
7157 emitcode ("anl", "a,#0x%02x", (unsigned char)
7158 ((unsigned char) (0xFF << (blen + bstr)) |
7159 (unsigned char) (0xFF >> (8 - bstr))));
7160 emitcode ("orl", "a,b");
7161 if (p_type == GPOINTER)
7162 emitcode ("pop", "b");
7169 emitcode ("mov", "@%s,a", rname);
7173 emitcode ("movx", "@dptr,a");
7177 emitcode ("lcall", "__gptrput");
7182 if (SPEC_BLEN (etype) <= 8)
7185 emitcode ("inc", "%s", rname);
7186 rLen = SPEC_BLEN (etype);
7188 /* now generate for lengths greater than one byte */
7192 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7204 emitcode ("mov", "@%s,a", rname);
7207 emitcode ("mov", "@%s,%s", rname, l);
7212 emitcode ("movx", "@dptr,a");
7217 emitcode ("lcall", "__gptrput");
7220 emitcode ("inc", "%s", rname);
7225 /* last last was not complete */
7228 /* save the byte & read byte */
7232 emitcode ("mov", "b,a");
7233 emitcode ("mov", "a,@%s", rname);
7237 emitcode ("mov", "b,a");
7238 emitcode ("movx", "a,@dptr");
7242 emitcode ("push", "b");
7243 emitcode ("push", "acc");
7244 emitcode ("lcall", "__gptrget");
7245 emitcode ("pop", "b");
7249 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7250 emitcode ("orl", "a,b");
7253 if (p_type == GPOINTER)
7254 emitcode ("pop", "b");
7260 emitcode ("mov", "@%s,a", rname);
7264 emitcode ("movx", "@dptr,a");
7268 emitcode ("lcall", "__gptrput");
7272 /*-----------------------------------------------------------------*/
7273 /* genDataPointerSet - remat pointer to data space */
7274 /*-----------------------------------------------------------------*/
7276 genDataPointerSet (operand * right,
7280 int size, offset = 0;
7281 char *l, buffer[256];
7283 aopOp (right, ic, FALSE);
7285 l = aopGet (AOP (result), 0, FALSE, TRUE);
7286 size = AOP_SIZE (right);
7290 sprintf (buffer, "(%s + %d)", l + 1, offset);
7292 sprintf (buffer, "%s", l + 1);
7293 emitcode ("mov", "%s,%s", buffer,
7294 aopGet (AOP (right), offset++, FALSE, FALSE));
7297 freeAsmop (right, NULL, ic, TRUE);
7298 freeAsmop (result, NULL, ic, TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* genNearPointerSet - emitcode for near pointer put */
7303 /*-----------------------------------------------------------------*/
7305 genNearPointerSet (operand * right,
7312 sym_link *retype, *letype;
7313 sym_link *ptype = operandType (result);
7315 retype = getSpec (operandType (right));
7316 letype = getSpec (ptype);
7317 aopOp (result, ic, FALSE);
7319 /* if the result is rematerializable &
7320 in data space & not a bit variable */
7321 if (AOP_TYPE (result) == AOP_IMMD &&
7322 DCL_TYPE (ptype) == POINTER &&
7323 !IS_BITVAR (retype) &&
7324 !IS_BITVAR (letype))
7326 genDataPointerSet (right, result, ic);
7330 /* if the value is already in a pointer register
7331 then don't need anything more */
7332 if (!AOP_INPREG (AOP (result)))
7334 /* otherwise get a free pointer register */
7336 preg = getFreePtr (ic, &aop, FALSE);
7337 emitcode ("mov", "%s,%s",
7339 aopGet (AOP (result), 0, FALSE, TRUE));
7343 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7345 freeAsmop (result, NULL, ic, TRUE);
7346 aopOp (right, ic, FALSE);
7348 /* if bitfield then unpack the bits */
7349 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7350 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7353 /* we have can just get the values */
7354 int size = AOP_SIZE (right);
7359 l = aopGet (AOP (right), offset, FALSE, TRUE);
7363 emitcode ("mov", "@%s,a", rname);
7366 emitcode ("mov", "@%s,%s", rname, l);
7368 emitcode ("inc", "%s", rname);
7373 /* now some housekeeping stuff */
7376 /* we had to allocate for this iCode */
7377 freeAsmop (NULL, aop, ic, TRUE);
7381 /* we did not allocate which means left
7382 already in a pointer register, then
7383 if size > 0 && this could be used again
7384 we have to point it back to where it
7386 if (AOP_SIZE (right) > 1 &&
7387 !OP_SYMBOL (result)->remat &&
7388 (OP_SYMBOL (result)->liveTo > ic->seq ||
7391 int size = AOP_SIZE (right) - 1;
7393 emitcode ("dec", "%s", rname);
7398 freeAsmop (right, NULL, ic, TRUE);
7403 /*-----------------------------------------------------------------*/
7404 /* genPagedPointerSet - emitcode for Paged pointer put */
7405 /*-----------------------------------------------------------------*/
7407 genPagedPointerSet (operand * right,
7414 sym_link *retype, *letype;
7416 retype = getSpec (operandType (right));
7417 letype = getSpec (operandType (result));
7419 aopOp (result, ic, FALSE);
7421 /* if the value is already in a pointer register
7422 then don't need anything more */
7423 if (!AOP_INPREG (AOP (result)))
7425 /* otherwise get a free pointer register */
7427 preg = getFreePtr (ic, &aop, FALSE);
7428 emitcode ("mov", "%s,%s",
7430 aopGet (AOP (result), 0, FALSE, TRUE));
7434 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7436 freeAsmop (result, NULL, ic, TRUE);
7437 aopOp (right, ic, FALSE);
7439 /* if bitfield then unpack the bits */
7440 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7441 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7444 /* we have can just get the values */
7445 int size = AOP_SIZE (right);
7450 l = aopGet (AOP (right), offset, FALSE, TRUE);
7453 emitcode ("movx", "@%s,a", rname);
7456 emitcode ("inc", "%s", rname);
7462 /* now some housekeeping stuff */
7465 /* we had to allocate for this iCode */
7466 freeAsmop (NULL, aop, ic, TRUE);
7470 /* we did not allocate which means left
7471 already in a pointer register, then
7472 if size > 0 && this could be used again
7473 we have to point it back to where it
7475 if (AOP_SIZE (right) > 1 &&
7476 !OP_SYMBOL (result)->remat &&
7477 (OP_SYMBOL (result)->liveTo > ic->seq ||
7480 int size = AOP_SIZE (right) - 1;
7482 emitcode ("dec", "%s", rname);
7487 freeAsmop (right, NULL, ic, TRUE);
7492 /*-----------------------------------------------------------------*/
7493 /* genFarPointerSet - set value from far space */
7494 /*-----------------------------------------------------------------*/
7496 genFarPointerSet (operand * right,
7497 operand * result, iCode * ic)
7500 sym_link *retype = getSpec (operandType (right));
7501 sym_link *letype = getSpec (operandType (result));
7502 aopOp (result, ic, FALSE);
7504 /* if the operand is already in dptr
7505 then we do nothing else we move the value to dptr */
7506 if (AOP_TYPE (result) != AOP_STR)
7508 /* if this is remateriazable */
7509 if (AOP_TYPE (result) == AOP_IMMD)
7510 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7512 { /* we need to get it byte by byte */
7513 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7514 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7517 /* so dptr know contains the address */
7518 freeAsmop (result, NULL, ic, TRUE);
7519 aopOp (right, ic, FALSE);
7521 /* if bit then unpack */
7522 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7523 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7526 size = AOP_SIZE (right);
7531 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7533 emitcode ("movx", "@dptr,a");
7535 emitcode ("inc", "dptr");
7539 freeAsmop (right, NULL, ic, TRUE);
7542 /*-----------------------------------------------------------------*/
7543 /* genGenPointerSet - set value from generic pointer space */
7544 /*-----------------------------------------------------------------*/
7546 genGenPointerSet (operand * right,
7547 operand * result, iCode * ic)
7550 sym_link *retype = getSpec (operandType (right));
7551 sym_link *letype = getSpec (operandType (result));
7553 aopOp (result, ic, FALSE);
7555 /* if the operand is already in dptr
7556 then we do nothing else we move the value to dptr */
7557 if (AOP_TYPE (result) != AOP_STR)
7559 /* if this is remateriazable */
7560 if (AOP_TYPE (result) == AOP_IMMD)
7562 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7563 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7566 { /* we need to get it byte by byte */
7567 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7568 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7569 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7572 /* so dptr know contains the address */
7573 freeAsmop (result, NULL, ic, TRUE);
7574 aopOp (right, ic, FALSE);
7576 /* if bit then unpack */
7577 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7578 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7581 size = AOP_SIZE (right);
7586 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7588 emitcode ("lcall", "__gptrput");
7590 emitcode ("inc", "dptr");
7594 freeAsmop (right, NULL, ic, TRUE);
7597 /*-----------------------------------------------------------------*/
7598 /* genPointerSet - stores the value into a pointer location */
7599 /*-----------------------------------------------------------------*/
7601 genPointerSet (iCode * ic)
7603 operand *right, *result;
7604 sym_link *type, *etype;
7607 right = IC_RIGHT (ic);
7608 result = IC_RESULT (ic);
7610 /* depending on the type of pointer we need to
7611 move it to the correct pointer register */
7612 type = operandType (result);
7613 etype = getSpec (type);
7614 /* if left is of type of pointer then it is simple */
7615 if (IS_PTR (type) && !IS_FUNC (type->next))
7617 p_type = DCL_TYPE (type);
7621 /* we have to go by the storage class */
7622 p_type = PTR_TYPE (SPEC_OCLS (etype));
7625 /* now that we have the pointer type we assign
7626 the pointer values */
7632 genNearPointerSet (right, result, ic);
7636 genPagedPointerSet (right, result, ic);
7640 genFarPointerSet (right, result, ic);
7644 genGenPointerSet (right, result, ic);
7650 /*-----------------------------------------------------------------*/
7651 /* genIfx - generate code for Ifx statement */
7652 /*-----------------------------------------------------------------*/
7654 genIfx (iCode * ic, iCode * popIc)
7656 operand *cond = IC_COND (ic);
7659 aopOp (cond, ic, FALSE);
7661 /* get the value into acc */
7662 if (AOP_TYPE (cond) != AOP_CRY)
7666 /* the result is now in the accumulator */
7667 freeAsmop (cond, NULL, ic, TRUE);
7669 /* if there was something to be popped then do it */
7673 /* if the condition is a bit variable */
7674 if (isbit && IS_ITEMP (cond) &&
7676 genIfxJump (ic, SPIL_LOC (cond)->rname);
7677 else if (isbit && !IS_ITEMP (cond))
7678 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7680 genIfxJump (ic, "a");
7685 /*-----------------------------------------------------------------*/
7686 /* genAddrOf - generates code for address of */
7687 /*-----------------------------------------------------------------*/
7689 genAddrOf (iCode * ic)
7691 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7694 aopOp (IC_RESULT (ic), ic, FALSE);
7696 /* if the operand is on the stack then we
7697 need to get the stack offset of this
7701 /* if it has an offset then we need to compute
7705 emitcode ("mov", "a,_bp");
7706 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7707 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7711 /* we can just move _bp */
7712 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7714 /* fill the result with zero */
7715 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7720 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7726 /* object not on stack then we need the name */
7727 size = AOP_SIZE (IC_RESULT (ic));
7732 char s[SDCC_NAME_MAX];
7734 sprintf (s, "#(%s >> %d)",
7738 sprintf (s, "#%s", sym->rname);
7739 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7743 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7747 /*-----------------------------------------------------------------*/
7748 /* genFarFarAssign - assignment when both are in far space */
7749 /*-----------------------------------------------------------------*/
7751 genFarFarAssign (operand * result, operand * right, iCode * ic)
7753 int size = AOP_SIZE (right);
7756 /* first push the right side on to the stack */
7759 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7761 emitcode ("push", "acc");
7764 freeAsmop (right, NULL, ic, FALSE);
7765 /* now assign DPTR to result */
7766 aopOp (result, ic, FALSE);
7767 size = AOP_SIZE (result);
7770 emitcode ("pop", "acc");
7771 aopPut (AOP (result), "a", --offset);
7773 freeAsmop (result, NULL, ic, FALSE);
7777 /*-----------------------------------------------------------------*/
7778 /* genAssign - generate code for assignment */
7779 /*-----------------------------------------------------------------*/
7781 genAssign (iCode * ic)
7783 operand *result, *right;
7785 unsigned long lit = 0L;
7787 result = IC_RESULT (ic);
7788 right = IC_RIGHT (ic);
7790 /* if they are the same */
7791 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7794 aopOp (right, ic, FALSE);
7796 /* special case both in far space */
7797 if ((AOP_TYPE (right) == AOP_DPTR ||
7798 AOP_TYPE (right) == AOP_DPTR2) &&
7799 IS_TRUE_SYMOP (result) &&
7800 isOperandInFarSpace (result))
7803 genFarFarAssign (result, right, ic);
7807 aopOp (result, ic, TRUE);
7809 /* if they are the same registers */
7810 if (sameRegs (AOP (right), AOP (result)))
7813 /* if the result is a bit */
7814 if (AOP_TYPE (result) == AOP_CRY)
7817 /* if the right size is a literal then
7818 we know what the value is */
7819 if (AOP_TYPE (right) == AOP_LIT)
7821 if (((int) operandLitValue (right)))
7822 aopPut (AOP (result), one, 0);
7824 aopPut (AOP (result), zero, 0);
7828 /* the right is also a bit variable */
7829 if (AOP_TYPE (right) == AOP_CRY)
7831 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7832 aopPut (AOP (result), "c", 0);
7838 aopPut (AOP (result), "a", 0);
7842 /* bit variables done */
7844 size = AOP_SIZE (result);
7846 if (AOP_TYPE (right) == AOP_LIT)
7847 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7849 (AOP_TYPE (result) != AOP_REG) &&
7850 (AOP_TYPE (right) == AOP_LIT) &&
7851 !IS_FLOAT (operandType (right)) &&
7854 emitcode ("clr", "a");
7857 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7858 aopPut (AOP (result), "a", size);
7860 aopPut (AOP (result),
7861 aopGet (AOP (right), size, FALSE, FALSE),
7869 aopPut (AOP (result),
7870 aopGet (AOP (right), offset, FALSE, FALSE),
7877 freeAsmop (right, NULL, ic, TRUE);
7878 freeAsmop (result, NULL, ic, TRUE);
7881 /*-----------------------------------------------------------------*/
7882 /* genJumpTab - genrates code for jump table */
7883 /*-----------------------------------------------------------------*/
7885 genJumpTab (iCode * ic)
7890 aopOp (IC_JTCOND (ic), ic, FALSE);
7891 /* get the condition into accumulator */
7892 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7894 /* multiply by three */
7895 emitcode ("add", "a,acc");
7896 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7897 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7899 jtab = newiTempLabel (NULL);
7900 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7901 emitcode ("jmp", "@a+dptr");
7902 emitcode ("", "%05d$:", jtab->key + 100);
7903 /* now generate the jump labels */
7904 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7905 jtab = setNextItem (IC_JTLABELS (ic)))
7906 emitcode ("ljmp", "%05d$", jtab->key + 100);
7910 /*-----------------------------------------------------------------*/
7911 /* genCast - gen code for casting */
7912 /*-----------------------------------------------------------------*/
7914 genCast (iCode * ic)
7916 operand *result = IC_RESULT (ic);
7917 sym_link *ctype = operandType (IC_LEFT (ic));
7918 sym_link *rtype = operandType (IC_RIGHT (ic));
7919 operand *right = IC_RIGHT (ic);
7922 /* if they are equivalent then do nothing */
7923 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7926 aopOp (right, ic, FALSE);
7927 aopOp (result, ic, FALSE);
7929 /* if the result is a bit */
7930 if (AOP_TYPE (result) == AOP_CRY)
7932 /* if the right size is a literal then
7933 we know what the value is */
7934 if (AOP_TYPE (right) == AOP_LIT)
7936 if (((int) operandLitValue (right)))
7937 aopPut (AOP (result), one, 0);
7939 aopPut (AOP (result), zero, 0);
7944 /* the right is also a bit variable */
7945 if (AOP_TYPE (right) == AOP_CRY)
7947 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7948 aopPut (AOP (result), "c", 0);
7954 aopPut (AOP (result), "a", 0);
7958 /* if they are the same size : or less */
7959 if (AOP_SIZE (result) <= AOP_SIZE (right))
7962 /* if they are in the same place */
7963 if (sameRegs (AOP (right), AOP (result)))
7966 /* if they in different places then copy */
7967 size = AOP_SIZE (result);
7971 aopPut (AOP (result),
7972 aopGet (AOP (right), offset, FALSE, FALSE),
7980 /* if the result is of type pointer */
7985 sym_link *type = operandType (right);
7986 sym_link *etype = getSpec (type);
7988 /* pointer to generic pointer */
7989 if (IS_GENPTR (ctype))
7994 p_type = DCL_TYPE (type);
7997 /* we have to go by the storage class */
7998 p_type = PTR_TYPE (SPEC_OCLS (etype));
8001 /* the first two bytes are known */
8002 size = GPTRSIZE - 1;
8006 aopPut (AOP (result),
8007 aopGet (AOP (right), offset, FALSE, FALSE),
8011 /* the last byte depending on type */
8029 /* this should never happen */
8030 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8031 "got unknown pointer type");
8034 aopPut (AOP (result), l, GPTRSIZE - 1);
8038 /* just copy the pointers */
8039 size = AOP_SIZE (result);
8043 aopPut (AOP (result),
8044 aopGet (AOP (right), offset, FALSE, FALSE),
8051 /* so we now know that the size of destination is greater
8052 than the size of the source */
8053 /* we move to result for the size of source */
8054 size = AOP_SIZE (right);
8058 aopPut (AOP (result),
8059 aopGet (AOP (right), offset, FALSE, FALSE),
8064 /* now depending on the sign of the source && destination */
8065 size = AOP_SIZE (result) - AOP_SIZE (right);
8066 /* if unsigned or not an integral type */
8067 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8070 aopPut (AOP (result), zero, offset++);
8074 /* we need to extend the sign :{ */
8075 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8078 emitcode ("rlc", "a");
8079 emitcode ("subb", "a,acc");
8081 aopPut (AOP (result), "a", offset++);
8084 /* we are done hurray !!!! */
8087 freeAsmop (right, NULL, ic, TRUE);
8088 freeAsmop (result, NULL, ic, TRUE);
8092 /*-----------------------------------------------------------------*/
8093 /* genDjnz - generate decrement & jump if not zero instrucion */
8094 /*-----------------------------------------------------------------*/
8096 genDjnz (iCode * ic, iCode * ifx)
8102 /* if the if condition has a false label
8103 then we cannot save */
8107 /* if the minus is not of the form
8109 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8110 !IS_OP_LITERAL (IC_RIGHT (ic)))
8113 if (operandLitValue (IC_RIGHT (ic)) != 1)
8116 /* if the size of this greater than one then no
8118 if (getSize (operandType (IC_RESULT (ic))) > 1)
8121 /* otherwise we can save BIG */
8122 lbl = newiTempLabel (NULL);
8123 lbl1 = newiTempLabel (NULL);
8125 aopOp (IC_RESULT (ic), ic, FALSE);
8127 if (IS_AOP_PREG (IC_RESULT (ic)))
8129 emitcode ("dec", "%s",
8130 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8131 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8132 emitcode ("jnz", "%05d$", lbl->key + 100);
8136 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8139 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8140 emitcode ("", "%05d$:", lbl->key + 100);
8141 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8142 emitcode ("", "%05d$:", lbl1->key + 100);
8144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8149 /*-----------------------------------------------------------------*/
8150 /* genReceive - generate code for a receive iCode */
8151 /*-----------------------------------------------------------------*/
8153 genReceive (iCode * ic)
8155 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8156 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8157 IS_TRUE_SYMOP (IC_RESULT (ic))))
8160 int size = getSize (operandType (IC_RESULT (ic)));
8161 int offset = fReturnSizeMCS51 - size;
8164 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8165 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8168 aopOp (IC_RESULT (ic), ic, FALSE);
8169 size = AOP_SIZE (IC_RESULT (ic));
8173 emitcode ("pop", "acc");
8174 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8181 aopOp (IC_RESULT (ic), ic, FALSE);
8183 assignResultValue (IC_RESULT (ic));
8186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8189 /*-----------------------------------------------------------------*/
8190 /* gen51Code - generate code for 8051 based controllers */
8191 /*-----------------------------------------------------------------*/
8193 gen51Code (iCode * lic)
8198 lineHead = lineCurr = NULL;
8200 /* print the allocation information */
8202 printAllocInfo (currFunc, codeOutFile);
8203 /* if debug information required */
8204 /* if (options.debug && currFunc) { */
8207 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8209 if (IS_STATIC (currFunc->etype))
8210 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8212 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8215 /* stack pointer name */
8216 if (options.useXstack)
8222 for (ic = lic; ic; ic = ic->next)
8225 if (cln != ic->lineno)
8230 emitcode ("", "C$%s$%d$%d$%d ==.",
8231 FileBaseName (ic->filename), ic->lineno,
8232 ic->level, ic->block);
8235 emitcode (";", "%s %d", ic->filename, ic->lineno);
8238 /* if the result is marked as
8239 spilt and rematerializable or code for
8240 this has already been generated then
8242 if (resultRemat (ic) || ic->generated)
8245 /* depending on the operation */
8265 /* IPOP happens only when trying to restore a
8266 spilt live range, if there is an ifx statement
8267 following this pop then the if statement might
8268 be using some of the registers being popped which
8269 would destory the contents of the register so
8270 we need to check for this condition and handle it */
8272 ic->next->op == IFX &&
8273 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8274 genIfx (ic->next, ic);
8292 genEndFunction (ic);
8312 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8329 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8333 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8340 /* note these two are xlated by algebraic equivalence
8341 during parsing SDCC.y */
8342 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8343 "got '>=' or '<=' shouldn't have come here");
8347 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8359 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8363 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8367 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8394 case GET_VALUE_AT_ADDRESS:
8399 if (POINTER_SET (ic))
8426 addSet (&_G.sendSet, ic);
8431 /* piCode(ic,stdout); */
8437 /* now we are ready to call the
8438 peep hole optimizer */
8439 if (!options.nopeep)
8440 peepHole (&lineHead);
8442 /* now do the actual printing */
8443 printLine (lineHead, codeOutFile);