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*8=8/16 bit multiplication */
3156 /*-----------------------------------------------------------------*/
3159 genMultOneByte (operand * left,
3163 sym_link *opetype = operandType (result);
3168 /* (if two literals, the value is computed before) */
3169 /* if one literal, literal on the right */
3170 if (AOP_TYPE (left) == AOP_LIT)
3177 size = AOP_SIZE (result);
3178 /* signed or unsigned */
3179 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3180 l = aopGet (AOP (left), 0, FALSE, FALSE);
3182 emitcode ("mul", "ab");
3183 /* if result size = 1, mul signed = mul unsigned */
3184 aopPut (AOP (result), "a", 0);
3187 if (SPEC_USIGN (opetype))
3189 aopPut (AOP (result), "b", 1);
3191 /* for filling the MSBs */
3192 emitcode ("clr", "a");
3196 emitcode ("mov", "a,b");
3198 /* adjust the MSB if left or right neg */
3200 /* if one literal */
3201 if (AOP_TYPE (right) == AOP_LIT)
3203 /* AND literal negative */
3204 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3206 /* adjust MSB (c==0 after mul) */
3207 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3212 lbl = newiTempLabel (NULL);
3213 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3214 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3215 emitcode ("", "%05d$:", (lbl->key + 100));
3216 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3217 lbl = newiTempLabel (NULL);
3218 emitcode ("jc", "%05d$", (lbl->key + 100));
3219 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3220 emitcode ("", "%05d$:", (lbl->key + 100));
3223 lbl = newiTempLabel (NULL);
3224 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3225 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3226 emitcode ("", "%05d$:", (lbl->key + 100));
3227 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3228 lbl = newiTempLabel (NULL);
3229 emitcode ("jc", "%05d$", (lbl->key + 100));
3230 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3231 emitcode ("", "%05d$:", (lbl->key + 100));
3233 aopPut (AOP (result), "a", 1);
3237 emitcode ("rlc", "a");
3238 emitcode ("subb", "a,acc");
3245 aopPut (AOP (result), "a", offset++);
3250 genMultOneByte (operand * left,
3254 sym_link *opetype = operandType (result);
3256 int size=AOP_SIZE(result);
3258 //emitcode (";",__FUNCTION__);
3259 if (size<1 || size>2) {
3260 // this should never happen
3261 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3262 AOP_SIZE(result), __FUNCTION__, lineno);
3266 /* (if two literals: the value is computed before) */
3267 /* if one literal, literal on the right */
3268 if (AOP_TYPE (left) == AOP_LIT)
3273 //emitcode (";", "swapped left and right");
3276 if (SPEC_USIGN(opetype)
3277 // ignore the sign of left and right, what else can we do?
3278 || (SPEC_USIGN(operandType(left)) &&
3279 SPEC_USIGN(operandType(right)))) {
3280 // just an unsigned 8*8=8/16 multiply
3281 //emitcode (";","unsigned");
3282 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3283 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3284 emitcode ("mul", "ab");
3285 aopPut (AOP (result), "a", 0);
3287 aopPut (AOP (result), "b", 1);
3292 // we have to do a signed multiply
3294 //emitcode (";", "signed");
3295 emitcode ("clr", "F0"); // reset sign flag
3296 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3297 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3299 lbl=newiTempLabel(NULL);
3300 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3301 // left side is negative, 8-bit two's complement, this fails for -128
3302 emitcode ("setb", "F0"); // set sign flag
3303 emitcode ("cpl", "a");
3304 emitcode ("inc", "a");
3306 emitcode ("", "%05d$:", lbl->key+100);
3307 emitcode ("xch", "a,b");
3310 if (AOP_TYPE(right)==AOP_LIT) {
3311 /* AND literal negative */
3312 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3313 // two's complement for literal<0
3314 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3315 emitcode ("cpl", "a");
3316 emitcode ("inc", "a");
3319 lbl=newiTempLabel(NULL);
3320 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3321 // right side is negative, 8-bit two's complement
3322 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3323 emitcode ("cpl", "a");
3324 emitcode ("inc", "a");
3325 emitcode ("", "%05d$:", lbl->key+100);
3327 emitcode ("mul", "ab");
3329 lbl=newiTempLabel(NULL);
3330 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3331 // only ONE op was negative, we have to do a 8/16-bit two's complement
3332 emitcode ("cpl", "a"); // lsb
3334 emitcode ("inc", "a");
3336 emitcode ("add", "a,#1");
3337 emitcode ("xch", "a,b");
3338 emitcode ("cpl", "a"); // msb
3339 emitcode ("addc", "a,#0");
3340 emitcode ("xch", "a,b");
3343 emitcode ("", "%05d$:", lbl->key+100);
3344 aopPut (AOP (result), "a", 0);
3346 aopPut (AOP (result), "b", 1);
3351 /*-----------------------------------------------------------------*/
3352 /* genMult - generates code for multiplication */
3353 /*-----------------------------------------------------------------*/
3355 genMult (iCode * ic)
3357 operand *left = IC_LEFT (ic);
3358 operand *right = IC_RIGHT (ic);
3359 operand *result = IC_RESULT (ic);
3361 /* assign the amsops */
3362 aopOp (left, ic, FALSE);
3363 aopOp (right, ic, FALSE);
3364 aopOp (result, ic, TRUE);
3366 /* special cases first */
3368 if (AOP_TYPE (left) == AOP_CRY &&
3369 AOP_TYPE (right) == AOP_CRY)
3371 genMultbits (left, right, result);
3375 /* if both are of size == 1 */
3376 if (AOP_SIZE (left) == 1 &&
3377 AOP_SIZE (right) == 1)
3379 genMultOneByte (left, right, result);
3383 /* should have been converted to function call */
3387 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3388 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3389 freeAsmop (result, NULL, ic, TRUE);
3392 /*-----------------------------------------------------------------*/
3393 /* genDivbits :- division of bits */
3394 /*-----------------------------------------------------------------*/
3396 genDivbits (operand * left,
3403 /* the result must be bit */
3404 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3405 l = aopGet (AOP (left), 0, FALSE, FALSE);
3409 emitcode ("div", "ab");
3410 emitcode ("rrc", "a");
3411 aopPut (AOP (result), "c", 0);
3414 /*-----------------------------------------------------------------*/
3415 /* genDivOneByte : 8 bit division */
3416 /*-----------------------------------------------------------------*/
3418 genDivOneByte (operand * left,
3422 sym_link *opetype = operandType (result);
3427 size = AOP_SIZE (result) - 1;
3429 /* signed or unsigned */
3430 if (SPEC_USIGN (opetype))
3432 /* unsigned is easy */
3433 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3434 l = aopGet (AOP (left), 0, FALSE, FALSE);
3436 emitcode ("div", "ab");
3437 aopPut (AOP (result), "a", 0);
3439 aopPut (AOP (result), zero, offset++);
3443 /* signed is a little bit more difficult */
3445 /* save the signs of the operands */
3446 l = aopGet (AOP (left), 0, FALSE, FALSE);
3448 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3449 emitcode ("push", "acc"); /* save it on the stack */
3451 /* now sign adjust for both left & right */
3452 l = aopGet (AOP (right), 0, FALSE, FALSE);
3454 lbl = newiTempLabel (NULL);
3455 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3456 emitcode ("cpl", "a");
3457 emitcode ("inc", "a");
3458 emitcode ("", "%05d$:", (lbl->key + 100));
3459 emitcode ("mov", "b,a");
3461 /* sign adjust left side */
3462 l = aopGet (AOP (left), 0, FALSE, FALSE);
3465 lbl = newiTempLabel (NULL);
3466 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3467 emitcode ("cpl", "a");
3468 emitcode ("inc", "a");
3469 emitcode ("", "%05d$:", (lbl->key + 100));
3471 /* now the division */
3472 emitcode ("div", "ab");
3473 /* we are interested in the lower order
3475 emitcode ("mov", "b,a");
3476 lbl = newiTempLabel (NULL);
3477 emitcode ("pop", "acc");
3478 /* if there was an over flow we don't
3479 adjust the sign of the result */
3480 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3481 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3483 emitcode ("clr", "a");
3484 emitcode ("subb", "a,b");
3485 emitcode ("mov", "b,a");
3486 emitcode ("", "%05d$:", (lbl->key + 100));
3488 /* now we are done */
3489 aopPut (AOP (result), "b", 0);
3492 emitcode ("mov", "c,b.7");
3493 emitcode ("subb", "a,acc");
3496 aopPut (AOP (result), "a", offset++);
3500 /*-----------------------------------------------------------------*/
3501 /* genDiv - generates code for division */
3502 /*-----------------------------------------------------------------*/
3506 operand *left = IC_LEFT (ic);
3507 operand *right = IC_RIGHT (ic);
3508 operand *result = IC_RESULT (ic);
3510 /* assign the amsops */
3511 aopOp (left, ic, FALSE);
3512 aopOp (right, ic, FALSE);
3513 aopOp (result, ic, TRUE);
3515 /* special cases first */
3517 if (AOP_TYPE (left) == AOP_CRY &&
3518 AOP_TYPE (right) == AOP_CRY)
3520 genDivbits (left, right, result);
3524 /* if both are of size == 1 */
3525 if (AOP_SIZE (left) == 1 &&
3526 AOP_SIZE (right) == 1)
3528 genDivOneByte (left, right, result);
3532 /* should have been converted to function call */
3535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3537 freeAsmop (result, NULL, ic, TRUE);
3540 /*-----------------------------------------------------------------*/
3541 /* genModbits :- modulus of bits */
3542 /*-----------------------------------------------------------------*/
3544 genModbits (operand * left,
3551 /* the result must be bit */
3552 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3553 l = aopGet (AOP (left), 0, FALSE, FALSE);
3557 emitcode ("div", "ab");
3558 emitcode ("mov", "a,b");
3559 emitcode ("rrc", "a");
3560 aopPut (AOP (result), "c", 0);
3563 /*-----------------------------------------------------------------*/
3564 /* genModOneByte : 8 bit modulus */
3565 /*-----------------------------------------------------------------*/
3567 genModOneByte (operand * left,
3571 sym_link *opetype = operandType (result);
3575 /* signed or unsigned */
3576 if (SPEC_USIGN (opetype))
3578 /* unsigned is easy */
3579 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3580 l = aopGet (AOP (left), 0, FALSE, FALSE);
3582 emitcode ("div", "ab");
3583 aopPut (AOP (result), "b", 0);
3587 /* signed is a little bit more difficult */
3589 /* save the signs of the operands */
3590 l = aopGet (AOP (left), 0, FALSE, FALSE);
3593 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3594 emitcode ("push", "acc"); /* save it on the stack */
3596 /* now sign adjust for both left & right */
3597 l = aopGet (AOP (right), 0, FALSE, FALSE);
3600 lbl = newiTempLabel (NULL);
3601 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3602 emitcode ("cpl", "a");
3603 emitcode ("inc", "a");
3604 emitcode ("", "%05d$:", (lbl->key + 100));
3605 emitcode ("mov", "b,a");
3607 /* sign adjust left side */
3608 l = aopGet (AOP (left), 0, FALSE, FALSE);
3611 lbl = newiTempLabel (NULL);
3612 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3613 emitcode ("cpl", "a");
3614 emitcode ("inc", "a");
3615 emitcode ("", "%05d$:", (lbl->key + 100));
3617 /* now the multiplication */
3618 emitcode ("div", "ab");
3619 /* we are interested in the lower order
3621 lbl = newiTempLabel (NULL);
3622 emitcode ("pop", "acc");
3623 /* if there was an over flow we don't
3624 adjust the sign of the result */
3625 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3626 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3628 emitcode ("clr", "a");
3629 emitcode ("subb", "a,b");
3630 emitcode ("mov", "b,a");
3631 emitcode ("", "%05d$:", (lbl->key + 100));
3633 /* now we are done */
3634 aopPut (AOP (result), "b", 0);
3638 /*-----------------------------------------------------------------*/
3639 /* genMod - generates code for division */
3640 /*-----------------------------------------------------------------*/
3644 operand *left = IC_LEFT (ic);
3645 operand *right = IC_RIGHT (ic);
3646 operand *result = IC_RESULT (ic);
3648 /* assign the amsops */
3649 aopOp (left, ic, FALSE);
3650 aopOp (right, ic, FALSE);
3651 aopOp (result, ic, TRUE);
3653 /* special cases first */
3655 if (AOP_TYPE (left) == AOP_CRY &&
3656 AOP_TYPE (right) == AOP_CRY)
3658 genModbits (left, right, result);
3662 /* if both are of size == 1 */
3663 if (AOP_SIZE (left) == 1 &&
3664 AOP_SIZE (right) == 1)
3666 genModOneByte (left, right, result);
3670 /* should have been converted to function call */
3674 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3675 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676 freeAsmop (result, NULL, ic, TRUE);
3679 /*-----------------------------------------------------------------*/
3680 /* genIfxJump :- will create a jump depending on the ifx */
3681 /*-----------------------------------------------------------------*/
3683 genIfxJump (iCode * ic, char *jval)
3686 symbol *tlbl = newiTempLabel (NULL);
3689 /* if true label then we jump if condition
3693 jlbl = IC_TRUE (ic);
3694 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3695 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3699 /* false label is present */
3700 jlbl = IC_FALSE (ic);
3701 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3702 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3704 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3705 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3707 emitcode (inst, "%05d$", tlbl->key + 100);
3708 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3709 emitcode ("", "%05d$:", tlbl->key + 100);
3711 /* mark the icode as generated */
3715 /*-----------------------------------------------------------------*/
3716 /* genCmp :- greater or less than comparison */
3717 /*-----------------------------------------------------------------*/
3719 genCmp (operand * left, operand * right,
3720 operand * result, iCode * ifx, int sign)
3722 int size, offset = 0;
3723 unsigned long lit = 0L;
3725 /* if left & right are bit variables */
3726 if (AOP_TYPE (left) == AOP_CRY &&
3727 AOP_TYPE (right) == AOP_CRY)
3729 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3730 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3734 /* subtract right from left if at the
3735 end the carry flag is set then we know that
3736 left is greater than right */
3737 size = max (AOP_SIZE (left), AOP_SIZE (right));
3739 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3740 if ((size == 1) && !sign &&
3741 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3743 symbol *lbl = newiTempLabel (NULL);
3744 emitcode ("cjne", "%s,%s,%05d$",
3745 aopGet (AOP (left), offset, FALSE, FALSE),
3746 aopGet (AOP (right), offset, FALSE, FALSE),
3748 emitcode ("", "%05d$:", lbl->key + 100);
3752 if (AOP_TYPE (right) == AOP_LIT)
3754 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3755 /* optimize if(x < 0) or if(x >= 0) */
3764 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3765 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3767 genIfxJump (ifx, "acc.7");
3771 emitcode ("rlc", "a");
3779 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3780 if (sign && size == 0)
3782 emitcode ("xrl", "a,#0x80");
3783 if (AOP_TYPE (right) == AOP_LIT)
3785 unsigned long lit = (unsigned long)
3786 floatFromVal (AOP (right)->aopu.aop_lit);
3787 emitcode ("subb", "a,#0x%02x",
3788 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3792 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3793 emitcode ("xrl", "b,#0x80");
3794 emitcode ("subb", "a,b");
3798 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3804 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3810 /* if the result is used in the next
3811 ifx conditional branch then generate
3812 code a little differently */
3814 genIfxJump (ifx, "c");
3817 /* leave the result in acc */
3821 /*-----------------------------------------------------------------*/
3822 /* genCmpGt :- greater than comparison */
3823 /*-----------------------------------------------------------------*/
3825 genCmpGt (iCode * ic, iCode * ifx)
3827 operand *left, *right, *result;
3828 sym_link *letype, *retype;
3831 left = IC_LEFT (ic);
3832 right = IC_RIGHT (ic);
3833 result = IC_RESULT (ic);
3835 letype = getSpec (operandType (left));
3836 retype = getSpec (operandType (right));
3837 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3838 /* assign the amsops */
3839 aopOp (left, ic, FALSE);
3840 aopOp (right, ic, FALSE);
3841 aopOp (result, ic, TRUE);
3843 genCmp (right, left, result, ifx, sign);
3845 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3846 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3847 freeAsmop (result, NULL, ic, TRUE);
3850 /*-----------------------------------------------------------------*/
3851 /* genCmpLt - less than comparisons */
3852 /*-----------------------------------------------------------------*/
3854 genCmpLt (iCode * ic, iCode * ifx)
3856 operand *left, *right, *result;
3857 sym_link *letype, *retype;
3860 left = IC_LEFT (ic);
3861 right = IC_RIGHT (ic);
3862 result = IC_RESULT (ic);
3864 letype = getSpec (operandType (left));
3865 retype = getSpec (operandType (right));
3866 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3868 /* assign the amsops */
3869 aopOp (left, ic, FALSE);
3870 aopOp (right, ic, FALSE);
3871 aopOp (result, ic, TRUE);
3873 genCmp (left, right, result, ifx, sign);
3875 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3876 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3877 freeAsmop (result, NULL, ic, TRUE);
3880 /*-----------------------------------------------------------------*/
3881 /* gencjneshort - compare and jump if not equal */
3882 /*-----------------------------------------------------------------*/
3884 gencjneshort (operand * left, operand * right, symbol * lbl)
3886 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3888 unsigned long lit = 0L;
3890 /* if the left side is a literal or
3891 if the right is in a pointer register and left
3893 if ((AOP_TYPE (left) == AOP_LIT) ||
3894 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3900 if (AOP_TYPE (right) == AOP_LIT)
3901 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3903 /* if the right side is a literal then anything goes */
3904 if (AOP_TYPE (right) == AOP_LIT &&
3905 AOP_TYPE (left) != AOP_DIR)
3909 emitcode ("cjne", "%s,%s,%05d$",
3910 aopGet (AOP (left), offset, FALSE, FALSE),
3911 aopGet (AOP (right), offset, FALSE, FALSE),
3917 /* if the right side is in a register or in direct space or
3918 if the left is a pointer register & right is not */
3919 else if (AOP_TYPE (right) == AOP_REG ||
3920 AOP_TYPE (right) == AOP_DIR ||
3921 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3922 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3926 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3927 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3928 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3929 emitcode ("jnz", "%05d$", lbl->key + 100);
3931 emitcode ("cjne", "a,%s,%05d$",
3932 aopGet (AOP (right), offset, FALSE, TRUE),
3939 /* right is a pointer reg need both a & b */
3942 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3943 if (strcmp (l, "b"))
3944 emitcode ("mov", "b,%s", l);
3945 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3946 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3952 /*-----------------------------------------------------------------*/
3953 /* gencjne - compare and jump if not equal */
3954 /*-----------------------------------------------------------------*/
3956 gencjne (operand * left, operand * right, symbol * lbl)
3958 symbol *tlbl = newiTempLabel (NULL);
3960 gencjneshort (left, right, lbl);
3962 emitcode ("mov", "a,%s", one);
3963 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3964 emitcode ("", "%05d$:", lbl->key + 100);
3965 emitcode ("clr", "a");
3966 emitcode ("", "%05d$:", tlbl->key + 100);
3969 /*-----------------------------------------------------------------*/
3970 /* genCmpEq - generates code for equal to */
3971 /*-----------------------------------------------------------------*/
3973 genCmpEq (iCode * ic, iCode * ifx)
3975 operand *left, *right, *result;
3977 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3978 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3979 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3981 /* if literal, literal on the right or
3982 if the right is in a pointer register and left
3984 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3985 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3987 operand *t = IC_RIGHT (ic);
3988 IC_RIGHT (ic) = IC_LEFT (ic);
3992 if (ifx && !AOP_SIZE (result))
3995 /* if they are both bit variables */
3996 if (AOP_TYPE (left) == AOP_CRY &&
3997 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3999 if (AOP_TYPE (right) == AOP_LIT)
4001 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4004 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4005 emitcode ("cpl", "c");
4009 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4013 emitcode ("clr", "c");
4015 /* AOP_TYPE(right) == AOP_CRY */
4019 symbol *lbl = newiTempLabel (NULL);
4020 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4021 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4022 emitcode ("cpl", "c");
4023 emitcode ("", "%05d$:", (lbl->key + 100));
4025 /* if true label then we jump if condition
4027 tlbl = newiTempLabel (NULL);
4030 emitcode ("jnc", "%05d$", tlbl->key + 100);
4031 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4035 emitcode ("jc", "%05d$", tlbl->key + 100);
4036 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4038 emitcode ("", "%05d$:", tlbl->key + 100);
4042 tlbl = newiTempLabel (NULL);
4043 gencjneshort (left, right, tlbl);
4046 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4047 emitcode ("", "%05d$:", tlbl->key + 100);
4051 symbol *lbl = newiTempLabel (NULL);
4052 emitcode ("sjmp", "%05d$", lbl->key + 100);
4053 emitcode ("", "%05d$:", tlbl->key + 100);
4054 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4055 emitcode ("", "%05d$:", lbl->key + 100);
4058 /* mark the icode as generated */
4063 /* if they are both bit variables */
4064 if (AOP_TYPE (left) == AOP_CRY &&
4065 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4067 if (AOP_TYPE (right) == AOP_LIT)
4069 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4073 emitcode ("cpl", "c");
4077 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4081 emitcode ("clr", "c");
4083 /* AOP_TYPE(right) == AOP_CRY */
4087 symbol *lbl = newiTempLabel (NULL);
4088 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4089 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4090 emitcode ("cpl", "c");
4091 emitcode ("", "%05d$:", (lbl->key + 100));
4094 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4101 genIfxJump (ifx, "c");
4104 /* if the result is used in an arithmetic operation
4105 then put the result in place */
4110 gencjne (left, right, newiTempLabel (NULL));
4111 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4113 aopPut (AOP (result), "a", 0);
4118 genIfxJump (ifx, "a");
4121 /* if the result is used in an arithmetic operation
4122 then put the result in place */
4123 if (AOP_TYPE (result) != AOP_CRY)
4125 /* leave the result in acc */
4129 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4131 freeAsmop (result, NULL, ic, TRUE);
4134 /*-----------------------------------------------------------------*/
4135 /* ifxForOp - returns the icode containing the ifx for operand */
4136 /*-----------------------------------------------------------------*/
4138 ifxForOp (operand * op, iCode * ic)
4140 /* if true symbol then needs to be assigned */
4141 if (IS_TRUE_SYMOP (op))
4144 /* if this has register type condition and
4145 the next instruction is ifx with the same operand
4146 and live to of the operand is upto the ifx only then */
4148 ic->next->op == IFX &&
4149 IC_COND (ic->next)->key == op->key &&
4150 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4155 /*-----------------------------------------------------------------*/
4156 /* genAndOp - for && operation */
4157 /*-----------------------------------------------------------------*/
4159 genAndOp (iCode * ic)
4161 operand *left, *right, *result;
4164 /* note here that && operations that are in an
4165 if statement are taken away by backPatchLabels
4166 only those used in arthmetic operations remain */
4167 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4168 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4169 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4171 /* if both are bit variables */
4172 if (AOP_TYPE (left) == AOP_CRY &&
4173 AOP_TYPE (right) == AOP_CRY)
4175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4176 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4181 tlbl = newiTempLabel (NULL);
4183 emitcode ("jz", "%05d$", tlbl->key + 100);
4185 emitcode ("", "%05d$:", tlbl->key + 100);
4189 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4190 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (result, NULL, ic, TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* genOrOp - for || operation */
4197 /*-----------------------------------------------------------------*/
4199 genOrOp (iCode * ic)
4201 operand *left, *right, *result;
4204 /* note here that || operations that are in an
4205 if statement are taken away by backPatchLabels
4206 only those used in arthmetic operations remain */
4207 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4208 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4209 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4211 /* if both are bit variables */
4212 if (AOP_TYPE (left) == AOP_CRY &&
4213 AOP_TYPE (right) == AOP_CRY)
4215 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4216 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4221 tlbl = newiTempLabel (NULL);
4223 emitcode ("jnz", "%05d$", tlbl->key + 100);
4225 emitcode ("", "%05d$:", tlbl->key + 100);
4229 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4230 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4231 freeAsmop (result, NULL, ic, TRUE);
4234 /*-----------------------------------------------------------------*/
4235 /* isLiteralBit - test if lit == 2^n */
4236 /*-----------------------------------------------------------------*/
4238 isLiteralBit (unsigned long lit)
4240 unsigned long pw[32] =
4241 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4242 0x100L, 0x200L, 0x400L, 0x800L,
4243 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4244 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4245 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4246 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4247 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4250 for (idx = 0; idx < 32; idx++)
4256 /*-----------------------------------------------------------------*/
4257 /* continueIfTrue - */
4258 /*-----------------------------------------------------------------*/
4260 continueIfTrue (iCode * ic)
4263 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4267 /*-----------------------------------------------------------------*/
4269 /*-----------------------------------------------------------------*/
4271 jumpIfTrue (iCode * ic)
4274 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4278 /*-----------------------------------------------------------------*/
4279 /* jmpTrueOrFalse - */
4280 /*-----------------------------------------------------------------*/
4282 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4284 // ugly but optimized by peephole
4287 symbol *nlbl = newiTempLabel (NULL);
4288 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4289 emitcode ("", "%05d$:", tlbl->key + 100);
4290 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4291 emitcode ("", "%05d$:", nlbl->key + 100);
4295 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4296 emitcode ("", "%05d$:", tlbl->key + 100);
4301 /*-----------------------------------------------------------------*/
4302 /* genAnd - code for and */
4303 /*-----------------------------------------------------------------*/
4305 genAnd (iCode * ic, iCode * ifx)
4307 operand *left, *right, *result;
4308 int size, offset = 0;
4309 unsigned long lit = 0L;
4313 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4314 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4315 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4318 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4320 AOP_TYPE (left), AOP_TYPE (right));
4321 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4323 AOP_SIZE (left), AOP_SIZE (right));
4326 /* if left is a literal & right is not then exchange them */
4327 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4328 AOP_NEEDSACC (left))
4330 operand *tmp = right;
4335 /* if result = right then exchange them */
4336 if (sameRegs (AOP (result), AOP (right)))
4338 operand *tmp = right;
4343 /* if right is bit then exchange them */
4344 if (AOP_TYPE (right) == AOP_CRY &&
4345 AOP_TYPE (left) != AOP_CRY)
4347 operand *tmp = right;
4351 if (AOP_TYPE (right) == AOP_LIT)
4352 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4354 size = AOP_SIZE (result);
4357 // result = bit & yy;
4358 if (AOP_TYPE (left) == AOP_CRY)
4360 // c = bit & literal;
4361 if (AOP_TYPE (right) == AOP_LIT)
4365 if (size && sameRegs (AOP (result), AOP (left)))
4368 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4373 if (size && (AOP_TYPE (result) == AOP_CRY))
4375 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4378 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4383 emitcode ("clr", "c");
4388 if (AOP_TYPE (right) == AOP_CRY)
4391 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4392 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4397 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4399 emitcode ("rrc", "a");
4400 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4408 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4409 genIfxJump (ifx, "c");
4413 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4414 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4415 if ((AOP_TYPE (right) == AOP_LIT) &&
4416 (AOP_TYPE (result) == AOP_CRY) &&
4417 (AOP_TYPE (left) != AOP_CRY))
4419 int posbit = isLiteralBit (lit);
4424 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4427 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4433 sprintf (buffer, "acc.%d", posbit & 0x07);
4434 genIfxJump (ifx, buffer);
4441 symbol *tlbl = newiTempLabel (NULL);
4442 int sizel = AOP_SIZE (left);
4444 emitcode ("setb", "c");
4447 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4449 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4451 if ((posbit = isLiteralBit (bytelit)) != 0)
4452 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4455 if (bytelit != 0x0FFL)
4456 emitcode ("anl", "a,%s",
4457 aopGet (AOP (right), offset, FALSE, TRUE));
4458 emitcode ("jnz", "%05d$", tlbl->key + 100);
4463 // bit = left & literal
4466 emitcode ("clr", "c");
4467 emitcode ("", "%05d$:", tlbl->key + 100);
4469 // if(left & literal)
4473 jmpTrueOrFalse (ifx, tlbl);
4481 /* if left is same as result */
4482 if (sameRegs (AOP (result), AOP (left)))
4484 for (; size--; offset++)
4486 if (AOP_TYPE (right) == AOP_LIT)
4488 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4490 else if (bytelit == 0)
4491 aopPut (AOP (result), zero, offset);
4492 else if (IS_AOP_PREG (result))
4494 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4495 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4496 aopPut (AOP (result), "a", offset);
4499 emitcode ("anl", "%s,%s",
4500 aopGet (AOP (left), offset, FALSE, TRUE),
4501 aopGet (AOP (right), offset, FALSE, FALSE));
4505 if (AOP_TYPE (left) == AOP_ACC)
4506 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4509 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4510 if (IS_AOP_PREG (result))
4512 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4513 aopPut (AOP (result), "a", offset);
4517 emitcode ("anl", "%s,a",
4518 aopGet (AOP (left), offset, FALSE, TRUE));
4525 // left & result in different registers
4526 if (AOP_TYPE (result) == AOP_CRY)
4529 // if(size), result in bit
4530 // if(!size && ifx), conditional oper: if(left & right)
4531 symbol *tlbl = newiTempLabel (NULL);
4532 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4534 emitcode ("setb", "c");
4537 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4538 emitcode ("anl", "a,%s",
4539 aopGet (AOP (left), offset, FALSE, FALSE));
4540 emitcode ("jnz", "%05d$", tlbl->key + 100);
4546 emitcode ("", "%05d$:", tlbl->key + 100);
4550 jmpTrueOrFalse (ifx, tlbl);
4554 for (; (size--); offset++)
4557 // result = left & right
4558 if (AOP_TYPE (right) == AOP_LIT)
4560 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4562 aopPut (AOP (result),
4563 aopGet (AOP (left), offset, FALSE, FALSE),
4567 else if (bytelit == 0)
4569 aopPut (AOP (result), zero, offset);
4573 // faster than result <- left, anl result,right
4574 // and better if result is SFR
4575 if (AOP_TYPE (left) == AOP_ACC)
4576 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4579 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4580 emitcode ("anl", "a,%s",
4581 aopGet (AOP (left), offset, FALSE, FALSE));
4583 aopPut (AOP (result), "a", offset);
4589 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4590 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4591 freeAsmop (result, NULL, ic, TRUE);
4594 /*-----------------------------------------------------------------*/
4595 /* genOr - code for or */
4596 /*-----------------------------------------------------------------*/
4598 genOr (iCode * ic, iCode * ifx)
4600 operand *left, *right, *result;
4601 int size, offset = 0;
4602 unsigned long lit = 0L;
4604 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4605 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4606 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4609 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4611 AOP_TYPE (left), AOP_TYPE (right));
4612 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4614 AOP_SIZE (left), AOP_SIZE (right));
4617 /* if left is a literal & right is not then exchange them */
4618 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4619 AOP_NEEDSACC (left))
4621 operand *tmp = right;
4626 /* if result = right then exchange them */
4627 if (sameRegs (AOP (result), AOP (right)))
4629 operand *tmp = right;
4634 /* if right is bit then exchange them */
4635 if (AOP_TYPE (right) == AOP_CRY &&
4636 AOP_TYPE (left) != AOP_CRY)
4638 operand *tmp = right;
4642 if (AOP_TYPE (right) == AOP_LIT)
4643 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4645 size = AOP_SIZE (result);
4649 if (AOP_TYPE (left) == AOP_CRY)
4651 if (AOP_TYPE (right) == AOP_LIT)
4653 // c = bit & literal;
4656 // lit != 0 => result = 1
4657 if (AOP_TYPE (result) == AOP_CRY)
4660 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4662 continueIfTrue (ifx);
4665 emitcode ("setb", "c");
4669 // lit == 0 => result = left
4670 if (size && sameRegs (AOP (result), AOP (left)))
4672 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4677 if (AOP_TYPE (right) == AOP_CRY)
4680 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4681 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4686 symbol *tlbl = newiTempLabel (NULL);
4687 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4688 emitcode ("setb", "c");
4689 emitcode ("jb", "%s,%05d$",
4690 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4692 emitcode ("jnz", "%05d$", tlbl->key + 100);
4693 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4695 jmpTrueOrFalse (ifx, tlbl);
4701 emitcode ("", "%05d$:", tlbl->key + 100);
4710 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4711 genIfxJump (ifx, "c");
4715 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4716 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4717 if ((AOP_TYPE (right) == AOP_LIT) &&
4718 (AOP_TYPE (result) == AOP_CRY) &&
4719 (AOP_TYPE (left) != AOP_CRY))
4725 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4727 continueIfTrue (ifx);
4732 // lit = 0, result = boolean(left)
4734 emitcode ("setb", "c");
4738 symbol *tlbl = newiTempLabel (NULL);
4739 emitcode ("jnz", "%05d$", tlbl->key + 100);
4741 emitcode ("", "%05d$:", tlbl->key + 100);
4745 genIfxJump (ifx, "a");
4753 /* if left is same as result */
4754 if (sameRegs (AOP (result), AOP (left)))
4756 for (; size--; offset++)
4758 if (AOP_TYPE (right) == AOP_LIT)
4760 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4762 else if (IS_AOP_PREG (left))
4764 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4765 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4766 aopPut (AOP (result), "a", offset);
4769 emitcode ("orl", "%s,%s",
4770 aopGet (AOP (left), offset, FALSE, TRUE),
4771 aopGet (AOP (right), offset, FALSE, FALSE));
4775 if (AOP_TYPE (left) == AOP_ACC)
4776 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4779 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4780 if (IS_AOP_PREG (left))
4782 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4783 aopPut (AOP (result), "a", offset);
4786 emitcode ("orl", "%s,a",
4787 aopGet (AOP (left), offset, FALSE, TRUE));
4794 // left & result in different registers
4795 if (AOP_TYPE (result) == AOP_CRY)
4798 // if(size), result in bit
4799 // if(!size && ifx), conditional oper: if(left | right)
4800 symbol *tlbl = newiTempLabel (NULL);
4801 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4803 emitcode ("setb", "c");
4806 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4807 emitcode ("orl", "a,%s",
4808 aopGet (AOP (left), offset, FALSE, FALSE));
4809 emitcode ("jnz", "%05d$", tlbl->key + 100);
4815 emitcode ("", "%05d$:", tlbl->key + 100);
4819 jmpTrueOrFalse (ifx, tlbl);
4822 for (; (size--); offset++)
4825 // result = left & right
4826 if (AOP_TYPE (right) == AOP_LIT)
4828 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4830 aopPut (AOP (result),
4831 aopGet (AOP (left), offset, FALSE, FALSE),
4836 // faster than result <- left, anl result,right
4837 // and better if result is SFR
4838 if (AOP_TYPE (left) == AOP_ACC)
4839 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4842 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4843 emitcode ("orl", "a,%s",
4844 aopGet (AOP (left), offset, FALSE, FALSE));
4846 aopPut (AOP (result), "a", offset);
4851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (result, NULL, ic, TRUE);
4856 /*-----------------------------------------------------------------*/
4857 /* genXor - code for xclusive or */
4858 /*-----------------------------------------------------------------*/
4860 genXor (iCode * ic, iCode * ifx)
4862 operand *left, *right, *result;
4863 int size, offset = 0;
4864 unsigned long lit = 0L;
4866 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4867 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4868 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4871 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4873 AOP_TYPE (left), AOP_TYPE (right));
4874 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4876 AOP_SIZE (left), AOP_SIZE (right));
4879 /* if left is a literal & right is not ||
4880 if left needs acc & right does not */
4881 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4882 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4884 operand *tmp = right;
4889 /* if result = right then exchange them */
4890 if (sameRegs (AOP (result), AOP (right)))
4892 operand *tmp = right;
4897 /* if right is bit then exchange them */
4898 if (AOP_TYPE (right) == AOP_CRY &&
4899 AOP_TYPE (left) != AOP_CRY)
4901 operand *tmp = right;
4905 if (AOP_TYPE (right) == AOP_LIT)
4906 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4908 size = AOP_SIZE (result);
4912 if (AOP_TYPE (left) == AOP_CRY)
4914 if (AOP_TYPE (right) == AOP_LIT)
4916 // c = bit & literal;
4919 // lit>>1 != 0 => result = 1
4920 if (AOP_TYPE (result) == AOP_CRY)
4923 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4925 continueIfTrue (ifx);
4928 emitcode ("setb", "c");
4935 // lit == 0, result = left
4936 if (size && sameRegs (AOP (result), AOP (left)))
4938 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4942 // lit == 1, result = not(left)
4943 if (size && sameRegs (AOP (result), AOP (left)))
4945 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4950 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951 emitcode ("cpl", "c");
4960 symbol *tlbl = newiTempLabel (NULL);
4961 if (AOP_TYPE (right) == AOP_CRY)
4964 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4968 int sizer = AOP_SIZE (right);
4970 // if val>>1 != 0, result = 1
4971 emitcode ("setb", "c");
4974 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4976 // test the msb of the lsb
4977 emitcode ("anl", "a,#0xfe");
4978 emitcode ("jnz", "%05d$", tlbl->key + 100);
4982 emitcode ("rrc", "a");
4984 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4985 emitcode ("cpl", "c");
4986 emitcode ("", "%05d$:", (tlbl->key + 100));
4993 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4994 genIfxJump (ifx, "c");
4998 if (sameRegs (AOP (result), AOP (left)))
5000 /* if left is same as result */
5001 for (; size--; offset++)
5003 if (AOP_TYPE (right) == AOP_LIT)
5005 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5007 else if (IS_AOP_PREG (left))
5009 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5010 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5011 aopPut (AOP (result), "a", offset);
5014 emitcode ("xrl", "%s,%s",
5015 aopGet (AOP (left), offset, FALSE, TRUE),
5016 aopGet (AOP (right), offset, FALSE, FALSE));
5020 if (AOP_TYPE (left) == AOP_ACC)
5021 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5024 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5025 if (IS_AOP_PREG (left))
5027 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5028 aopPut (AOP (result), "a", offset);
5031 emitcode ("xrl", "%s,a",
5032 aopGet (AOP (left), offset, FALSE, TRUE));
5039 // left & result in different registers
5040 if (AOP_TYPE (result) == AOP_CRY)
5043 // if(size), result in bit
5044 // if(!size && ifx), conditional oper: if(left ^ right)
5045 symbol *tlbl = newiTempLabel (NULL);
5046 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5048 emitcode ("setb", "c");
5051 if ((AOP_TYPE (right) == AOP_LIT) &&
5052 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5054 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5058 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5059 emitcode ("xrl", "a,%s",
5060 aopGet (AOP (left), offset, FALSE, FALSE));
5062 emitcode ("jnz", "%05d$", tlbl->key + 100);
5068 emitcode ("", "%05d$:", tlbl->key + 100);
5072 jmpTrueOrFalse (ifx, tlbl);
5075 for (; (size--); offset++)
5078 // result = left & right
5079 if (AOP_TYPE (right) == AOP_LIT)
5081 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5083 aopPut (AOP (result),
5084 aopGet (AOP (left), offset, FALSE, FALSE),
5089 // faster than result <- left, anl result,right
5090 // and better if result is SFR
5091 if (AOP_TYPE (left) == AOP_ACC)
5092 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5095 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5096 emitcode ("xrl", "a,%s",
5097 aopGet (AOP (left), offset, FALSE, TRUE));
5099 aopPut (AOP (result), "a", offset);
5104 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5105 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5106 freeAsmop (result, NULL, ic, TRUE);
5109 /*-----------------------------------------------------------------*/
5110 /* genInline - write the inline code out */
5111 /*-----------------------------------------------------------------*/
5113 genInline (iCode * ic)
5115 char buffer[MAX_INLINEASM];
5119 _G.inLine += (!options.asmpeep);
5120 strcpy (buffer, IC_INLINE (ic));
5122 /* emit each line as a code */
5147 /* emitcode("",buffer); */
5148 _G.inLine -= (!options.asmpeep);
5151 /*-----------------------------------------------------------------*/
5152 /* genRRC - rotate right with carry */
5153 /*-----------------------------------------------------------------*/
5157 operand *left, *result;
5158 int size, offset = 0;
5161 /* rotate right with carry */
5162 left = IC_LEFT (ic);
5163 result = IC_RESULT (ic);
5164 aopOp (left, ic, FALSE);
5165 aopOp (result, ic, FALSE);
5167 /* move it to the result */
5168 size = AOP_SIZE (result);
5173 l = aopGet (AOP (left), offset, FALSE, FALSE);
5175 emitcode ("rrc", "a");
5176 if (AOP_SIZE (result) > 1)
5177 aopPut (AOP (result), "a", offset--);
5179 /* now we need to put the carry into the
5180 highest order byte of the result */
5181 if (AOP_SIZE (result) > 1)
5183 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5186 emitcode ("mov", "acc.7,c");
5187 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5188 freeAsmop (left, NULL, ic, TRUE);
5189 freeAsmop (result, NULL, ic, TRUE);
5192 /*-----------------------------------------------------------------*/
5193 /* genRLC - generate code for rotate left with carry */
5194 /*-----------------------------------------------------------------*/
5198 operand *left, *result;
5199 int size, offset = 0;
5202 /* rotate right with carry */
5203 left = IC_LEFT (ic);
5204 result = IC_RESULT (ic);
5205 aopOp (left, ic, FALSE);
5206 aopOp (result, ic, FALSE);
5208 /* move it to the result */
5209 size = AOP_SIZE (result);
5213 l = aopGet (AOP (left), offset, FALSE, FALSE);
5215 emitcode ("add", "a,acc");
5216 if (AOP_SIZE (result) > 1)
5217 aopPut (AOP (result), "a", offset++);
5220 l = aopGet (AOP (left), offset, FALSE, FALSE);
5222 emitcode ("rlc", "a");
5223 if (AOP_SIZE (result) > 1)
5224 aopPut (AOP (result), "a", offset++);
5227 /* now we need to put the carry into the
5228 highest order byte of the result */
5229 if (AOP_SIZE (result) > 1)
5231 l = aopGet (AOP (result), 0, FALSE, FALSE);
5234 emitcode ("mov", "acc.0,c");
5235 aopPut (AOP (result), "a", 0);
5236 freeAsmop (left, NULL, ic, TRUE);
5237 freeAsmop (result, NULL, ic, TRUE);
5240 /*-----------------------------------------------------------------*/
5241 /* genGetHbit - generates code get highest order bit */
5242 /*-----------------------------------------------------------------*/
5244 genGetHbit (iCode * ic)
5246 operand *left, *result;
5247 left = IC_LEFT (ic);
5248 result = IC_RESULT (ic);
5249 aopOp (left, ic, FALSE);
5250 aopOp (result, ic, FALSE);
5252 /* get the highest order byte into a */
5253 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5254 if (AOP_TYPE (result) == AOP_CRY)
5256 emitcode ("rlc", "a");
5261 emitcode ("rl", "a");
5262 emitcode ("anl", "a,#0x01");
5267 freeAsmop (left, NULL, ic, TRUE);
5268 freeAsmop (result, NULL, ic, TRUE);
5271 /*-----------------------------------------------------------------*/
5272 /* AccRol - rotate left accumulator by known count */
5273 /*-----------------------------------------------------------------*/
5275 AccRol (int shCount)
5277 shCount &= 0x0007; // shCount : 0..7
5284 emitcode ("rl", "a");
5287 emitcode ("rl", "a");
5288 emitcode ("rl", "a");
5291 emitcode ("swap", "a");
5292 emitcode ("rr", "a");
5295 emitcode ("swap", "a");
5298 emitcode ("swap", "a");
5299 emitcode ("rl", "a");
5302 emitcode ("rr", "a");
5303 emitcode ("rr", "a");
5306 emitcode ("rr", "a");
5311 /*-----------------------------------------------------------------*/
5312 /* AccLsh - left shift accumulator by known count */
5313 /*-----------------------------------------------------------------*/
5315 AccLsh (int shCount)
5320 emitcode ("add", "a,acc");
5321 else if (shCount == 2)
5323 emitcode ("add", "a,acc");
5324 emitcode ("add", "a,acc");
5328 /* rotate left accumulator */
5330 /* and kill the lower order bits */
5331 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5336 /*-----------------------------------------------------------------*/
5337 /* AccRsh - right shift accumulator by known count */
5338 /*-----------------------------------------------------------------*/
5340 AccRsh (int shCount)
5347 emitcode ("rrc", "a");
5351 /* rotate right accumulator */
5352 AccRol (8 - shCount);
5353 /* and kill the higher order bits */
5354 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5359 /*-----------------------------------------------------------------*/
5360 /* AccSRsh - signed right shift accumulator by known count */
5361 /*-----------------------------------------------------------------*/
5363 AccSRsh (int shCount)
5370 emitcode ("mov", "c,acc.7");
5371 emitcode ("rrc", "a");
5373 else if (shCount == 2)
5375 emitcode ("mov", "c,acc.7");
5376 emitcode ("rrc", "a");
5377 emitcode ("mov", "c,acc.7");
5378 emitcode ("rrc", "a");
5382 tlbl = newiTempLabel (NULL);
5383 /* rotate right accumulator */
5384 AccRol (8 - shCount);
5385 /* and kill the higher order bits */
5386 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5387 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5388 emitcode ("orl", "a,#0x%02x",
5389 (unsigned char) ~SRMask[shCount]);
5390 emitcode ("", "%05d$:", tlbl->key + 100);
5395 /*-----------------------------------------------------------------*/
5396 /* shiftR1Left2Result - shift right one byte from left to result */
5397 /*-----------------------------------------------------------------*/
5399 shiftR1Left2Result (operand * left, int offl,
5400 operand * result, int offr,
5401 int shCount, int sign)
5403 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5404 /* shift right accumulator */
5409 aopPut (AOP (result), "a", offr);
5412 /*-----------------------------------------------------------------*/
5413 /* shiftL1Left2Result - shift left one byte from left to result */
5414 /*-----------------------------------------------------------------*/
5416 shiftL1Left2Result (operand * left, int offl,
5417 operand * result, int offr, int shCount)
5420 l = aopGet (AOP (left), offl, FALSE, FALSE);
5422 /* shift left accumulator */
5424 aopPut (AOP (result), "a", offr);
5427 /*-----------------------------------------------------------------*/
5428 /* movLeft2Result - move byte from left to result */
5429 /*-----------------------------------------------------------------*/
5431 movLeft2Result (operand * left, int offl,
5432 operand * result, int offr, int sign)
5435 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5437 l = aopGet (AOP (left), offl, FALSE, FALSE);
5439 if (*l == '@' && (IS_AOP_PREG (result)))
5441 emitcode ("mov", "a,%s", l);
5442 aopPut (AOP (result), "a", offr);
5447 aopPut (AOP (result), l, offr);
5450 /* MSB sign in acc.7 ! */
5451 if (getDataSize (left) == offl + 1)
5453 emitcode ("mov", "a,%s", l);
5454 aopPut (AOP (result), "a", offr);
5461 /*-----------------------------------------------------------------*/
5462 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5463 /*-----------------------------------------------------------------*/
5467 emitcode ("rrc", "a");
5468 emitcode ("xch", "a,%s", x);
5469 emitcode ("rrc", "a");
5470 emitcode ("xch", "a,%s", x);
5473 /*-----------------------------------------------------------------*/
5474 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5475 /*-----------------------------------------------------------------*/
5479 emitcode ("xch", "a,%s", x);
5480 emitcode ("rlc", "a");
5481 emitcode ("xch", "a,%s", x);
5482 emitcode ("rlc", "a");
5485 /*-----------------------------------------------------------------*/
5486 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5487 /*-----------------------------------------------------------------*/
5491 emitcode ("xch", "a,%s", x);
5492 emitcode ("add", "a,acc");
5493 emitcode ("xch", "a,%s", x);
5494 emitcode ("rlc", "a");
5497 /*-----------------------------------------------------------------*/
5498 /* AccAXLsh - left shift a:x by known count (0..7) */
5499 /*-----------------------------------------------------------------*/
5501 AccAXLsh (char *x, int shCount)
5516 case 5: // AAAAABBB:CCCCCDDD
5518 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5520 emitcode ("anl", "a,#0x%02x",
5521 SLMask[shCount]); // BBB00000:CCCCCDDD
5523 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5525 AccRol (shCount); // DDDCCCCC:BBB00000
5527 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5529 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5531 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5533 emitcode ("anl", "a,#0x%02x",
5534 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5536 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5538 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5541 case 6: // AAAAAABB:CCCCCCDD
5542 emitcode ("anl", "a,#0x%02x",
5543 SRMask[shCount]); // 000000BB:CCCCCCDD
5544 emitcode ("mov", "c,acc.0"); // c = B
5545 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5547 AccAXRrl1 (x); // BCCCCCCD:D000000B
5548 AccAXRrl1 (x); // BBCCCCCC:DD000000
5550 emitcode("rrc","a");
5551 emitcode("xch","a,%s", x);
5552 emitcode("rrc","a");
5553 emitcode("mov","c,acc.0"); //<< get correct bit
5554 emitcode("xch","a,%s", x);
5556 emitcode("rrc","a");
5557 emitcode("xch","a,%s", x);
5558 emitcode("rrc","a");
5559 emitcode("xch","a,%s", x);
5562 case 7: // a:x <<= 7
5564 emitcode ("anl", "a,#0x%02x",
5565 SRMask[shCount]); // 0000000B:CCCCCCCD
5567 emitcode ("mov", "c,acc.0"); // c = B
5569 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5571 AccAXRrl1 (x); // BCCCCCCC:D0000000
5579 /*-----------------------------------------------------------------*/
5580 /* AccAXRsh - right shift a:x known count (0..7) */
5581 /*-----------------------------------------------------------------*/
5583 AccAXRsh (char *x, int shCount)
5591 AccAXRrl1 (x); // 0->a:x
5596 AccAXRrl1 (x); // 0->a:x
5599 AccAXRrl1 (x); // 0->a:x
5604 case 5: // AAAAABBB:CCCCCDDD = a:x
5606 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5608 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5610 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5612 emitcode ("anl", "a,#0x%02x",
5613 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5615 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5617 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5619 emitcode ("anl", "a,#0x%02x",
5620 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5622 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5624 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5626 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5629 case 6: // AABBBBBB:CCDDDDDD
5631 emitcode ("mov", "c,acc.7");
5632 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5634 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5636 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5638 emitcode ("anl", "a,#0x%02x",
5639 SRMask[shCount]); // 000000AA:BBBBBBCC
5642 case 7: // ABBBBBBB:CDDDDDDD
5644 emitcode ("mov", "c,acc.7"); // c = A
5646 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5648 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5650 emitcode ("anl", "a,#0x%02x",
5651 SRMask[shCount]); // 0000000A:BBBBBBBC
5659 /*-----------------------------------------------------------------*/
5660 /* AccAXRshS - right shift signed a:x known count (0..7) */
5661 /*-----------------------------------------------------------------*/
5663 AccAXRshS (char *x, int shCount)
5671 emitcode ("mov", "c,acc.7");
5672 AccAXRrl1 (x); // s->a:x
5676 emitcode ("mov", "c,acc.7");
5677 AccAXRrl1 (x); // s->a:x
5679 emitcode ("mov", "c,acc.7");
5680 AccAXRrl1 (x); // s->a:x
5685 case 5: // AAAAABBB:CCCCCDDD = a:x
5687 tlbl = newiTempLabel (NULL);
5688 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5690 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5692 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5694 emitcode ("anl", "a,#0x%02x",
5695 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5697 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5699 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5701 emitcode ("anl", "a,#0x%02x",
5702 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5704 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5706 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5708 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5710 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5711 emitcode ("orl", "a,#0x%02x",
5712 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5714 emitcode ("", "%05d$:", tlbl->key + 100);
5715 break; // SSSSAAAA:BBBCCCCC
5717 case 6: // AABBBBBB:CCDDDDDD
5719 tlbl = newiTempLabel (NULL);
5720 emitcode ("mov", "c,acc.7");
5721 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5723 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5725 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5727 emitcode ("anl", "a,#0x%02x",
5728 SRMask[shCount]); // 000000AA:BBBBBBCC
5730 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5731 emitcode ("orl", "a,#0x%02x",
5732 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5734 emitcode ("", "%05d$:", tlbl->key + 100);
5736 case 7: // ABBBBBBB:CDDDDDDD
5738 tlbl = newiTempLabel (NULL);
5739 emitcode ("mov", "c,acc.7"); // c = A
5741 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5743 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5745 emitcode ("anl", "a,#0x%02x",
5746 SRMask[shCount]); // 0000000A:BBBBBBBC
5748 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5749 emitcode ("orl", "a,#0x%02x",
5750 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5752 emitcode ("", "%05d$:", tlbl->key + 100);
5759 /*-----------------------------------------------------------------*/
5760 /* shiftL2Left2Result - shift left two bytes from left to result */
5761 /*-----------------------------------------------------------------*/
5763 shiftL2Left2Result (operand * left, int offl,
5764 operand * result, int offr, int shCount)
5766 if (sameRegs (AOP (result), AOP (left)) &&
5767 ((offl + MSB16) == offr))
5769 /* don't crash result[offr] */
5770 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5771 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5775 movLeft2Result (left, offl, result, offr, 0);
5776 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5778 /* ax << shCount (x = lsb(result)) */
5779 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5780 aopPut (AOP (result), "a", offr + MSB16);
5784 /*-----------------------------------------------------------------*/
5785 /* shiftR2Left2Result - shift right two bytes from left to result */
5786 /*-----------------------------------------------------------------*/
5788 shiftR2Left2Result (operand * left, int offl,
5789 operand * result, int offr,
5790 int shCount, int sign)
5792 if (sameRegs (AOP (result), AOP (left)) &&
5793 ((offl + MSB16) == offr))
5795 /* don't crash result[offr] */
5796 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5797 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5801 movLeft2Result (left, offl, result, offr, 0);
5802 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5804 /* a:x >> shCount (x = lsb(result)) */
5806 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5808 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5809 if (getDataSize (result) > 1)
5810 aopPut (AOP (result), "a", offr + MSB16);
5813 /*-----------------------------------------------------------------*/
5814 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5815 /*-----------------------------------------------------------------*/
5817 shiftLLeftOrResult (operand * left, int offl,
5818 operand * result, int offr, int shCount)
5820 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5821 /* shift left accumulator */
5823 /* or with result */
5824 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5825 /* back to result */
5826 aopPut (AOP (result), "a", offr);
5829 /*-----------------------------------------------------------------*/
5830 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5831 /*-----------------------------------------------------------------*/
5833 shiftRLeftOrResult (operand * left, int offl,
5834 operand * result, int offr, int shCount)
5836 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5837 /* shift right accumulator */
5839 /* or with result */
5840 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5841 /* back to result */
5842 aopPut (AOP (result), "a", offr);
5845 /*-----------------------------------------------------------------*/
5846 /* genlshOne - left shift a one byte quantity by known count */
5847 /*-----------------------------------------------------------------*/
5849 genlshOne (operand * result, operand * left, int shCount)
5851 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5854 /*-----------------------------------------------------------------*/
5855 /* genlshTwo - left shift two bytes by known amount != 0 */
5856 /*-----------------------------------------------------------------*/
5858 genlshTwo (operand * result, operand * left, int shCount)
5862 size = getDataSize (result);
5864 /* if shCount >= 8 */
5872 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5874 movLeft2Result (left, LSB, result, MSB16, 0);
5876 aopPut (AOP (result), zero, LSB);
5879 /* 1 <= shCount <= 7 */
5883 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5885 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5889 /*-----------------------------------------------------------------*/
5890 /* shiftLLong - shift left one long from left to result */
5891 /* offl = LSB or MSB16 */
5892 /*-----------------------------------------------------------------*/
5894 shiftLLong (operand * left, operand * result, int offr)
5897 int size = AOP_SIZE (result);
5899 if (size >= LSB + offr)
5901 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5903 emitcode ("add", "a,acc");
5904 if (sameRegs (AOP (left), AOP (result)) &&
5905 size >= MSB16 + offr && offr != LSB)
5906 emitcode ("xch", "a,%s",
5907 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5909 aopPut (AOP (result), "a", LSB + offr);
5912 if (size >= MSB16 + offr)
5914 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5916 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5919 emitcode ("rlc", "a");
5920 if (sameRegs (AOP (left), AOP (result)) &&
5921 size >= MSB24 + offr && offr != LSB)
5922 emitcode ("xch", "a,%s",
5923 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5925 aopPut (AOP (result), "a", MSB16 + offr);
5928 if (size >= MSB24 + offr)
5930 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5932 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5935 emitcode ("rlc", "a");
5936 if (sameRegs (AOP (left), AOP (result)) &&
5937 size >= MSB32 + offr && offr != LSB)
5938 emitcode ("xch", "a,%s",
5939 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5941 aopPut (AOP (result), "a", MSB24 + offr);
5944 if (size > MSB32 + offr)
5946 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5948 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5951 emitcode ("rlc", "a");
5952 aopPut (AOP (result), "a", MSB32 + offr);
5955 aopPut (AOP (result), zero, LSB);
5958 /*-----------------------------------------------------------------*/
5959 /* genlshFour - shift four byte by a known amount != 0 */
5960 /*-----------------------------------------------------------------*/
5962 genlshFour (operand * result, operand * left, int shCount)
5966 size = AOP_SIZE (result);
5968 /* if shifting more that 3 bytes */
5973 /* lowest order of left goes to the highest
5974 order of the destination */
5975 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5977 movLeft2Result (left, LSB, result, MSB32, 0);
5978 aopPut (AOP (result), zero, LSB);
5979 aopPut (AOP (result), zero, MSB16);
5980 aopPut (AOP (result), zero, MSB32);
5984 /* more than two bytes */
5985 else if (shCount >= 16)
5987 /* lower order two bytes goes to higher order two bytes */
5989 /* if some more remaining */
5991 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5994 movLeft2Result (left, MSB16, result, MSB32, 0);
5995 movLeft2Result (left, LSB, result, MSB24, 0);
5997 aopPut (AOP (result), zero, MSB16);
5998 aopPut (AOP (result), zero, LSB);
6002 /* if more than 1 byte */
6003 else if (shCount >= 8)
6005 /* lower order three bytes goes to higher order three bytes */
6010 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6012 movLeft2Result (left, LSB, result, MSB16, 0);
6018 movLeft2Result (left, MSB24, result, MSB32, 0);
6019 movLeft2Result (left, MSB16, result, MSB24, 0);
6020 movLeft2Result (left, LSB, result, MSB16, 0);
6021 aopPut (AOP (result), zero, LSB);
6023 else if (shCount == 1)
6024 shiftLLong (left, result, MSB16);
6027 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6028 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6029 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6030 aopPut (AOP (result), zero, LSB);
6035 /* 1 <= shCount <= 7 */
6036 else if (shCount <= 2)
6038 shiftLLong (left, result, LSB);
6040 shiftLLong (result, result, LSB);
6042 /* 3 <= shCount <= 7, optimize */
6045 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6046 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6047 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6051 /*-----------------------------------------------------------------*/
6052 /* genLeftShiftLiteral - left shifting by known count */
6053 /*-----------------------------------------------------------------*/
6055 genLeftShiftLiteral (operand * left,
6060 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6063 freeAsmop (right, NULL, ic, TRUE);
6065 aopOp (left, ic, FALSE);
6066 aopOp (result, ic, FALSE);
6068 size = getSize (operandType (result));
6071 emitcode ("; shift left ", "result %d, left %d", size,
6075 /* I suppose that the left size >= result size */
6080 movLeft2Result (left, size, result, size, 0);
6084 else if (shCount >= (size * 8))
6086 aopPut (AOP (result), zero, size);
6092 genlshOne (result, left, shCount);
6097 genlshTwo (result, left, shCount);
6101 genlshFour (result, left, shCount);
6105 freeAsmop (left, NULL, ic, TRUE);
6106 freeAsmop (result, NULL, ic, TRUE);
6109 /*-----------------------------------------------------------------*/
6110 /* genLeftShift - generates code for left shifting */
6111 /*-----------------------------------------------------------------*/
6113 genLeftShift (iCode * ic)
6115 operand *left, *right, *result;
6118 symbol *tlbl, *tlbl1;
6120 right = IC_RIGHT (ic);
6121 left = IC_LEFT (ic);
6122 result = IC_RESULT (ic);
6124 aopOp (right, ic, FALSE);
6126 /* if the shift count is known then do it
6127 as efficiently as possible */
6128 if (AOP_TYPE (right) == AOP_LIT)
6130 genLeftShiftLiteral (left, right, result, ic);
6134 /* shift count is unknown then we have to form
6135 a loop get the loop count in B : Note: we take
6136 only the lower order byte since shifting
6137 more that 32 bits make no sense anyway, ( the
6138 largest size of an object can be only 32 bits ) */
6140 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6141 emitcode ("inc", "b");
6142 freeAsmop (right, NULL, ic, TRUE);
6143 aopOp (left, ic, FALSE);
6144 aopOp (result, ic, FALSE);
6146 /* now move the left to the result if they are not the
6148 if (!sameRegs (AOP (left), AOP (result)) &&
6149 AOP_SIZE (result) > 1)
6152 size = AOP_SIZE (result);
6156 l = aopGet (AOP (left), offset, FALSE, TRUE);
6157 if (*l == '@' && (IS_AOP_PREG (result)))
6160 emitcode ("mov", "a,%s", l);
6161 aopPut (AOP (result), "a", offset);
6164 aopPut (AOP (result), l, offset);
6169 tlbl = newiTempLabel (NULL);
6170 size = AOP_SIZE (result);
6172 tlbl1 = newiTempLabel (NULL);
6174 /* if it is only one byte then */
6177 symbol *tlbl1 = newiTempLabel (NULL);
6179 l = aopGet (AOP (left), 0, FALSE, FALSE);
6181 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6182 emitcode ("", "%05d$:", tlbl->key + 100);
6183 emitcode ("add", "a,acc");
6184 emitcode ("", "%05d$:", tlbl1->key + 100);
6185 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6186 aopPut (AOP (result), "a", 0);
6190 reAdjustPreg (AOP (result));
6192 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6193 emitcode ("", "%05d$:", tlbl->key + 100);
6194 l = aopGet (AOP (result), offset, FALSE, FALSE);
6196 emitcode ("add", "a,acc");
6197 aopPut (AOP (result), "a", offset++);
6200 l = aopGet (AOP (result), offset, FALSE, FALSE);
6202 emitcode ("rlc", "a");
6203 aopPut (AOP (result), "a", offset++);
6205 reAdjustPreg (AOP (result));
6207 emitcode ("", "%05d$:", tlbl1->key + 100);
6208 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6210 freeAsmop (left, NULL, ic, TRUE);
6211 freeAsmop (result, NULL, ic, TRUE);
6214 /*-----------------------------------------------------------------*/
6215 /* genrshOne - right shift a one byte quantity by known count */
6216 /*-----------------------------------------------------------------*/
6218 genrshOne (operand * result, operand * left,
6219 int shCount, int sign)
6221 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6224 /*-----------------------------------------------------------------*/
6225 /* genrshTwo - right shift two bytes by known amount != 0 */
6226 /*-----------------------------------------------------------------*/
6228 genrshTwo (operand * result, operand * left,
6229 int shCount, int sign)
6231 /* if shCount >= 8 */
6236 shiftR1Left2Result (left, MSB16, result, LSB,
6239 movLeft2Result (left, MSB16, result, LSB, sign);
6240 addSign (result, MSB16, sign);
6243 /* 1 <= shCount <= 7 */
6245 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6248 /*-----------------------------------------------------------------*/
6249 /* shiftRLong - shift right one long from left to result */
6250 /* offl = LSB or MSB16 */
6251 /*-----------------------------------------------------------------*/
6253 shiftRLong (operand * left, int offl,
6254 operand * result, int sign)
6257 emitcode ("clr", "c");
6258 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6260 emitcode ("mov", "c,acc.7");
6261 emitcode ("rrc", "a");
6262 aopPut (AOP (result), "a", MSB32 - offl);
6264 /* add sign of "a" */
6265 addSign (result, MSB32, sign);
6267 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6268 emitcode ("rrc", "a");
6269 aopPut (AOP (result), "a", MSB24 - offl);
6271 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6272 emitcode ("rrc", "a");
6273 aopPut (AOP (result), "a", MSB16 - offl);
6277 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6278 emitcode ("rrc", "a");
6279 aopPut (AOP (result), "a", LSB);
6283 /*-----------------------------------------------------------------*/
6284 /* genrshFour - shift four byte by a known amount != 0 */
6285 /*-----------------------------------------------------------------*/
6287 genrshFour (operand * result, operand * left,
6288 int shCount, int sign)
6290 /* if shifting more that 3 bytes */
6295 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6297 movLeft2Result (left, MSB32, result, LSB, sign);
6298 addSign (result, MSB16, sign);
6300 else if (shCount >= 16)
6304 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6307 movLeft2Result (left, MSB24, result, LSB, 0);
6308 movLeft2Result (left, MSB32, result, MSB16, sign);
6310 addSign (result, MSB24, sign);
6312 else if (shCount >= 8)
6316 shiftRLong (left, MSB16, result, sign);
6317 else if (shCount == 0)
6319 movLeft2Result (left, MSB16, result, LSB, 0);
6320 movLeft2Result (left, MSB24, result, MSB16, 0);
6321 movLeft2Result (left, MSB32, result, MSB24, sign);
6322 addSign (result, MSB32, sign);
6326 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6327 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6328 /* the last shift is signed */
6329 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6330 addSign (result, MSB32, sign);
6334 { /* 1 <= shCount <= 7 */
6337 shiftRLong (left, LSB, result, sign);
6339 shiftRLong (result, LSB, result, sign);
6343 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6344 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6345 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6350 /*-----------------------------------------------------------------*/
6351 /* genRightShiftLiteral - right shifting by known count */
6352 /*-----------------------------------------------------------------*/
6354 genRightShiftLiteral (operand * left,
6360 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6363 freeAsmop (right, NULL, ic, TRUE);
6365 aopOp (left, ic, FALSE);
6366 aopOp (result, ic, FALSE);
6369 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6373 size = getDataSize (left);
6374 /* test the LEFT size !!! */
6376 /* I suppose that the left size >= result size */
6379 size = getDataSize (result);
6381 movLeft2Result (left, size, result, size, 0);
6384 else if (shCount >= (size * 8))
6387 /* get sign in acc.7 */
6388 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6389 addSign (result, LSB, sign);
6396 genrshOne (result, left, shCount, sign);
6400 genrshTwo (result, left, shCount, sign);
6404 genrshFour (result, left, shCount, sign);
6410 freeAsmop (left, NULL, ic, TRUE);
6411 freeAsmop (result, NULL, ic, TRUE);
6415 /*-----------------------------------------------------------------*/
6416 /* genSignedRightShift - right shift of signed number */
6417 /*-----------------------------------------------------------------*/
6419 genSignedRightShift (iCode * ic)
6421 operand *right, *left, *result;
6424 symbol *tlbl, *tlbl1;
6426 /* we do it the hard way put the shift count in b
6427 and loop thru preserving the sign */
6429 right = IC_RIGHT (ic);
6430 left = IC_LEFT (ic);
6431 result = IC_RESULT (ic);
6433 aopOp (right, ic, FALSE);
6436 if (AOP_TYPE (right) == AOP_LIT)
6438 genRightShiftLiteral (left, right, result, ic, 1);
6441 /* shift count is unknown then we have to form
6442 a loop get the loop count in B : Note: we take
6443 only the lower order byte since shifting
6444 more that 32 bits make no sense anyway, ( the
6445 largest size of an object can be only 32 bits ) */
6447 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6448 emitcode ("inc", "b");
6449 freeAsmop (right, NULL, ic, TRUE);
6450 aopOp (left, ic, FALSE);
6451 aopOp (result, ic, FALSE);
6453 /* now move the left to the result if they are not the
6455 if (!sameRegs (AOP (left), AOP (result)) &&
6456 AOP_SIZE (result) > 1)
6459 size = AOP_SIZE (result);
6463 l = aopGet (AOP (left), offset, FALSE, TRUE);
6464 if (*l == '@' && IS_AOP_PREG (result))
6467 emitcode ("mov", "a,%s", l);
6468 aopPut (AOP (result), "a", offset);
6471 aopPut (AOP (result), l, offset);
6476 /* mov the highest order bit to OVR */
6477 tlbl = newiTempLabel (NULL);
6478 tlbl1 = newiTempLabel (NULL);
6480 size = AOP_SIZE (result);
6482 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6483 emitcode ("rlc", "a");
6484 emitcode ("mov", "ov,c");
6485 /* if it is only one byte then */
6488 l = aopGet (AOP (left), 0, FALSE, FALSE);
6490 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6491 emitcode ("", "%05d$:", tlbl->key + 100);
6492 emitcode ("mov", "c,ov");
6493 emitcode ("rrc", "a");
6494 emitcode ("", "%05d$:", tlbl1->key + 100);
6495 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6496 aopPut (AOP (result), "a", 0);
6500 reAdjustPreg (AOP (result));
6501 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6502 emitcode ("", "%05d$:", tlbl->key + 100);
6503 emitcode ("mov", "c,ov");
6506 l = aopGet (AOP (result), offset, FALSE, FALSE);
6508 emitcode ("rrc", "a");
6509 aopPut (AOP (result), "a", offset--);
6511 reAdjustPreg (AOP (result));
6512 emitcode ("", "%05d$:", tlbl1->key + 100);
6513 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6516 freeAsmop (left, NULL, ic, TRUE);
6517 freeAsmop (result, NULL, ic, TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* genRightShift - generate code for right shifting */
6522 /*-----------------------------------------------------------------*/
6524 genRightShift (iCode * ic)
6526 operand *right, *left, *result;
6530 symbol *tlbl, *tlbl1;
6532 /* if signed then we do it the hard way preserve the
6533 sign bit moving it inwards */
6534 retype = getSpec (operandType (IC_RESULT (ic)));
6536 if (!SPEC_USIGN (retype))
6538 genSignedRightShift (ic);
6542 /* signed & unsigned types are treated the same : i.e. the
6543 signed is NOT propagated inwards : quoting from the
6544 ANSI - standard : "for E1 >> E2, is equivalent to division
6545 by 2**E2 if unsigned or if it has a non-negative value,
6546 otherwise the result is implementation defined ", MY definition
6547 is that the sign does not get propagated */
6549 right = IC_RIGHT (ic);
6550 left = IC_LEFT (ic);
6551 result = IC_RESULT (ic);
6553 aopOp (right, ic, FALSE);
6555 /* if the shift count is known then do it
6556 as efficiently as possible */
6557 if (AOP_TYPE (right) == AOP_LIT)
6559 genRightShiftLiteral (left, right, result, ic, 0);
6563 /* shift count is unknown then we have to form
6564 a loop get the loop count in B : Note: we take
6565 only the lower order byte since shifting
6566 more that 32 bits make no sense anyway, ( the
6567 largest size of an object can be only 32 bits ) */
6569 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6570 emitcode ("inc", "b");
6571 freeAsmop (right, NULL, ic, TRUE);
6572 aopOp (left, ic, FALSE);
6573 aopOp (result, ic, FALSE);
6575 /* now move the left to the result if they are not the
6577 if (!sameRegs (AOP (left), AOP (result)) &&
6578 AOP_SIZE (result) > 1)
6581 size = AOP_SIZE (result);
6585 l = aopGet (AOP (left), offset, FALSE, TRUE);
6586 if (*l == '@' && IS_AOP_PREG (result))
6589 emitcode ("mov", "a,%s", l);
6590 aopPut (AOP (result), "a", offset);
6593 aopPut (AOP (result), l, offset);
6598 tlbl = newiTempLabel (NULL);
6599 tlbl1 = newiTempLabel (NULL);
6600 size = AOP_SIZE (result);
6603 /* if it is only one byte then */
6606 l = aopGet (AOP (left), 0, FALSE, FALSE);
6608 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6609 emitcode ("", "%05d$:", tlbl->key + 100);
6611 emitcode ("rrc", "a");
6612 emitcode ("", "%05d$:", tlbl1->key + 100);
6613 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6614 aopPut (AOP (result), "a", 0);
6618 reAdjustPreg (AOP (result));
6619 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6620 emitcode ("", "%05d$:", tlbl->key + 100);
6624 l = aopGet (AOP (result), offset, FALSE, FALSE);
6626 emitcode ("rrc", "a");
6627 aopPut (AOP (result), "a", offset--);
6629 reAdjustPreg (AOP (result));
6631 emitcode ("", "%05d$:", tlbl1->key + 100);
6632 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6635 freeAsmop (left, NULL, ic, TRUE);
6636 freeAsmop (result, NULL, ic, TRUE);
6639 /*-----------------------------------------------------------------*/
6640 /* genUnpackBits - generates code for unpacking bits */
6641 /*-----------------------------------------------------------------*/
6643 genUnpackBits (operand * result, char *rname, int ptype)
6651 etype = getSpec (operandType (result));
6652 rsize = getSize (operandType (result));
6653 /* read the first byte */
6659 emitcode ("mov", "a,@%s", rname);
6663 emitcode ("movx", "a,@%s", rname);
6667 emitcode ("movx", "a,@dptr");
6671 emitcode ("clr", "a");
6672 emitcode ("movc", "a,%s", "@a+dptr");
6676 emitcode ("lcall", "__gptrget");
6680 rlen = SPEC_BLEN (etype);
6682 /* if we have bitdisplacement then it fits */
6683 /* into this byte completely or if length is */
6684 /* less than a byte */
6685 if ((shCnt = SPEC_BSTR (etype)) ||
6686 (SPEC_BLEN (etype) <= 8))
6689 /* shift right acc */
6692 emitcode ("anl", "a,#0x%02x",
6693 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6694 aopPut (AOP (result), "a", offset++);
6698 /* bit field did not fit in a byte */
6699 aopPut (AOP (result), "a", offset++);
6708 emitcode ("inc", "%s", rname);
6709 emitcode ("mov", "a,@%s", rname);
6713 emitcode ("inc", "%s", rname);
6714 emitcode ("movx", "a,@%s", rname);
6718 emitcode ("inc", "dptr");
6719 emitcode ("movx", "a,@dptr");
6723 emitcode ("clr", "a");
6724 emitcode ("inc", "dptr");
6725 emitcode ("movc", "a", "@a+dptr");
6729 emitcode ("inc", "dptr");
6730 emitcode ("lcall", "__gptrget");
6735 /* if we are done */
6739 aopPut (AOP (result), "a", offset++);
6745 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6747 aopPut (AOP (result), "a", offset++);
6755 aopPut (AOP (result), zero, offset++);
6761 /*-----------------------------------------------------------------*/
6762 /* genDataPointerGet - generates code when ptr offset is known */
6763 /*-----------------------------------------------------------------*/
6765 genDataPointerGet (operand * left,
6771 int size, offset = 0;
6772 aopOp (result, ic, TRUE);
6774 /* get the string representation of the name */
6775 l = aopGet (AOP (left), 0, FALSE, TRUE);
6776 size = AOP_SIZE (result);
6780 sprintf (buffer, "(%s + %d)", l + 1, offset);
6782 sprintf (buffer, "%s", l + 1);
6783 aopPut (AOP (result), buffer, offset++);
6786 freeAsmop (left, NULL, ic, TRUE);
6787 freeAsmop (result, NULL, ic, TRUE);
6790 /*-----------------------------------------------------------------*/
6791 /* genNearPointerGet - emitcode for near pointer fetch */
6792 /*-----------------------------------------------------------------*/
6794 genNearPointerGet (operand * left,
6801 sym_link *rtype, *retype;
6802 sym_link *ltype = operandType (left);
6805 rtype = operandType (result);
6806 retype = getSpec (rtype);
6808 aopOp (left, ic, FALSE);
6810 /* if left is rematerialisable and
6811 result is not bit variable type and
6812 the left is pointer to data space i.e
6813 lower 128 bytes of space */
6814 if (AOP_TYPE (left) == AOP_IMMD &&
6815 !IS_BITVAR (retype) &&
6816 DCL_TYPE (ltype) == POINTER)
6818 genDataPointerGet (left, result, ic);
6822 /* if the value is already in a pointer register
6823 then don't need anything more */
6824 if (!AOP_INPREG (AOP (left)))
6826 /* otherwise get a free pointer register */
6828 preg = getFreePtr (ic, &aop, FALSE);
6829 emitcode ("mov", "%s,%s",
6831 aopGet (AOP (left), 0, FALSE, TRUE));
6835 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6837 freeAsmop (left, NULL, ic, TRUE);
6838 aopOp (result, ic, FALSE);
6840 /* if bitfield then unpack the bits */
6841 if (IS_BITVAR (retype))
6842 genUnpackBits (result, rname, POINTER);
6845 /* we have can just get the values */
6846 int size = AOP_SIZE (result);
6851 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6854 emitcode ("mov", "a,@%s", rname);
6855 aopPut (AOP (result), "a", offset);
6859 sprintf (buffer, "@%s", rname);
6860 aopPut (AOP (result), buffer, offset);
6864 emitcode ("inc", "%s", rname);
6868 /* now some housekeeping stuff */
6871 /* we had to allocate for this iCode */
6872 freeAsmop (NULL, aop, ic, TRUE);
6876 /* we did not allocate which means left
6877 already in a pointer register, then
6878 if size > 0 && this could be used again
6879 we have to point it back to where it
6881 if (AOP_SIZE (result) > 1 &&
6882 !OP_SYMBOL (left)->remat &&
6883 (OP_SYMBOL (left)->liveTo > ic->seq ||
6886 int size = AOP_SIZE (result) - 1;
6888 emitcode ("dec", "%s", rname);
6893 freeAsmop (result, NULL, ic, TRUE);
6897 /*-----------------------------------------------------------------*/
6898 /* genPagedPointerGet - emitcode for paged pointer fetch */
6899 /*-----------------------------------------------------------------*/
6901 genPagedPointerGet (operand * left,
6908 sym_link *rtype, *retype;
6910 rtype = operandType (result);
6911 retype = getSpec (rtype);
6913 aopOp (left, ic, FALSE);
6915 /* if the value is already in a pointer register
6916 then don't need anything more */
6917 if (!AOP_INPREG (AOP (left)))
6919 /* otherwise get a free pointer register */
6921 preg = getFreePtr (ic, &aop, FALSE);
6922 emitcode ("mov", "%s,%s",
6924 aopGet (AOP (left), 0, FALSE, TRUE));
6928 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6930 freeAsmop (left, NULL, ic, TRUE);
6931 aopOp (result, ic, FALSE);
6933 /* if bitfield then unpack the bits */
6934 if (IS_BITVAR (retype))
6935 genUnpackBits (result, rname, PPOINTER);
6938 /* we have can just get the values */
6939 int size = AOP_SIZE (result);
6945 emitcode ("movx", "a,@%s", rname);
6946 aopPut (AOP (result), "a", offset);
6951 emitcode ("inc", "%s", rname);
6955 /* now some housekeeping stuff */
6958 /* we had to allocate for this iCode */
6959 freeAsmop (NULL, aop, ic, TRUE);
6963 /* we did not allocate which means left
6964 already in a pointer register, then
6965 if size > 0 && this could be used again
6966 we have to point it back to where it
6968 if (AOP_SIZE (result) > 1 &&
6969 !OP_SYMBOL (left)->remat &&
6970 (OP_SYMBOL (left)->liveTo > ic->seq ||
6973 int size = AOP_SIZE (result) - 1;
6975 emitcode ("dec", "%s", rname);
6980 freeAsmop (result, NULL, ic, TRUE);
6985 /*-----------------------------------------------------------------*/
6986 /* genFarPointerGet - gget value from far space */
6987 /*-----------------------------------------------------------------*/
6989 genFarPointerGet (operand * left,
6990 operand * result, iCode * ic)
6993 sym_link *retype = getSpec (operandType (result));
6995 aopOp (left, ic, FALSE);
6997 /* if the operand is already in dptr
6998 then we do nothing else we move the value to dptr */
6999 if (AOP_TYPE (left) != AOP_STR)
7001 /* if this is remateriazable */
7002 if (AOP_TYPE (left) == AOP_IMMD)
7003 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7005 { /* we need to get it byte by byte */
7006 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7007 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, 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", FPOINTER);
7019 size = AOP_SIZE (result);
7024 emitcode ("movx", "a,@dptr");
7025 aopPut (AOP (result), "a", offset++);
7027 emitcode ("inc", "dptr");
7031 freeAsmop (result, NULL, ic, TRUE);
7034 /*-----------------------------------------------------------------*/
7035 /* emitcodePointerGet - gget value from code space */
7036 /*-----------------------------------------------------------------*/
7038 emitcodePointerGet (operand * left,
7039 operand * result, iCode * ic)
7042 sym_link *retype = getSpec (operandType (result));
7044 aopOp (left, ic, FALSE);
7046 /* if the operand is already in dptr
7047 then we do nothing else we move the value to dptr */
7048 if (AOP_TYPE (left) != AOP_STR)
7050 /* if this is remateriazable */
7051 if (AOP_TYPE (left) == AOP_IMMD)
7052 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7054 { /* we need to get it byte by byte */
7055 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7056 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7059 /* so dptr know contains the address */
7060 freeAsmop (left, NULL, ic, TRUE);
7061 aopOp (result, ic, FALSE);
7063 /* if bit then unpack */
7064 if (IS_BITVAR (retype))
7065 genUnpackBits (result, "dptr", CPOINTER);
7068 size = AOP_SIZE (result);
7073 emitcode ("clr", "a");
7074 emitcode ("movc", "a,@a+dptr");
7075 aopPut (AOP (result), "a", offset++);
7077 emitcode ("inc", "dptr");
7081 freeAsmop (result, NULL, ic, TRUE);
7084 /*-----------------------------------------------------------------*/
7085 /* genGenPointerGet - gget value from generic pointer space */
7086 /*-----------------------------------------------------------------*/
7088 genGenPointerGet (operand * left,
7089 operand * result, iCode * ic)
7092 sym_link *retype = getSpec (operandType (result));
7094 aopOp (left, ic, FALSE);
7096 /* if the operand is already in dptr
7097 then we do nothing else we move the value to dptr */
7098 if (AOP_TYPE (left) != AOP_STR)
7100 /* if this is remateriazable */
7101 if (AOP_TYPE (left) == AOP_IMMD)
7103 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7104 emitcode ("mov", "b,#%d", pointerCode (retype));
7107 { /* we need to get it byte by byte */
7108 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7109 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7110 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7113 /* so dptr know contains the address */
7114 freeAsmop (left, NULL, ic, TRUE);
7115 aopOp (result, ic, FALSE);
7117 /* if bit then unpack */
7118 if (IS_BITVAR (retype))
7119 genUnpackBits (result, "dptr", GPOINTER);
7122 size = AOP_SIZE (result);
7127 emitcode ("lcall", "__gptrget");
7128 aopPut (AOP (result), "a", offset++);
7130 emitcode ("inc", "dptr");
7134 freeAsmop (result, NULL, ic, TRUE);
7137 /*-----------------------------------------------------------------*/
7138 /* genPointerGet - generate code for pointer get */
7139 /*-----------------------------------------------------------------*/
7141 genPointerGet (iCode * ic)
7143 operand *left, *result;
7144 sym_link *type, *etype;
7147 left = IC_LEFT (ic);
7148 result = IC_RESULT (ic);
7150 /* depending on the type of pointer we need to
7151 move it to the correct pointer register */
7152 type = operandType (left);
7153 etype = getSpec (type);
7154 /* if left is of type of pointer then it is simple */
7155 if (IS_PTR (type) && !IS_FUNC (type->next))
7156 p_type = DCL_TYPE (type);
7159 /* we have to go by the storage class */
7160 p_type = PTR_TYPE (SPEC_OCLS (etype));
7162 /* if (SPEC_OCLS(etype)->codesp ) { */
7163 /* p_type = CPOINTER ; */
7166 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7167 /* p_type = FPOINTER ; */
7169 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7170 /* p_type = PPOINTER; */
7172 /* if (SPEC_OCLS(etype) == idata ) */
7173 /* p_type = IPOINTER; */
7175 /* p_type = POINTER ; */
7178 /* now that we have the pointer type we assign
7179 the pointer values */
7185 genNearPointerGet (left, result, ic);
7189 genPagedPointerGet (left, result, ic);
7193 genFarPointerGet (left, result, ic);
7197 emitcodePointerGet (left, result, ic);
7201 genGenPointerGet (left, result, ic);
7207 /*-----------------------------------------------------------------*/
7208 /* genPackBits - generates code for packed bit storage */
7209 /*-----------------------------------------------------------------*/
7211 genPackBits (sym_link * etype,
7213 char *rname, int p_type)
7221 blen = SPEC_BLEN (etype);
7222 bstr = SPEC_BSTR (etype);
7224 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7227 /* if the bit lenth is less than or */
7228 /* it exactly fits a byte then */
7229 if (SPEC_BLEN (etype) <= 8)
7231 shCount = SPEC_BSTR (etype);
7233 /* shift left acc */
7236 if (SPEC_BLEN (etype) < 8)
7237 { /* if smaller than a byte */
7243 emitcode ("mov", "b,a");
7244 emitcode ("mov", "a,@%s", rname);
7248 emitcode ("mov", "b,a");
7249 emitcode ("movx", "a,@dptr");
7253 emitcode ("push", "b");
7254 emitcode ("push", "acc");
7255 emitcode ("lcall", "__gptrget");
7256 emitcode ("pop", "b");
7260 emitcode ("anl", "a,#0x%02x", (unsigned char)
7261 ((unsigned char) (0xFF << (blen + bstr)) |
7262 (unsigned char) (0xFF >> (8 - bstr))));
7263 emitcode ("orl", "a,b");
7264 if (p_type == GPOINTER)
7265 emitcode ("pop", "b");
7272 emitcode ("mov", "@%s,a", rname);
7276 emitcode ("movx", "@dptr,a");
7280 emitcode ("lcall", "__gptrput");
7285 if (SPEC_BLEN (etype) <= 8)
7288 emitcode ("inc", "%s", rname);
7289 rLen = SPEC_BLEN (etype);
7291 /* now generate for lengths greater than one byte */
7295 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7307 emitcode ("mov", "@%s,a", rname);
7310 emitcode ("mov", "@%s,%s", rname, l);
7315 emitcode ("movx", "@dptr,a");
7320 emitcode ("lcall", "__gptrput");
7323 emitcode ("inc", "%s", rname);
7328 /* last last was not complete */
7331 /* save the byte & read byte */
7335 emitcode ("mov", "b,a");
7336 emitcode ("mov", "a,@%s", rname);
7340 emitcode ("mov", "b,a");
7341 emitcode ("movx", "a,@dptr");
7345 emitcode ("push", "b");
7346 emitcode ("push", "acc");
7347 emitcode ("lcall", "__gptrget");
7348 emitcode ("pop", "b");
7352 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7353 emitcode ("orl", "a,b");
7356 if (p_type == GPOINTER)
7357 emitcode ("pop", "b");
7363 emitcode ("mov", "@%s,a", rname);
7367 emitcode ("movx", "@dptr,a");
7371 emitcode ("lcall", "__gptrput");
7375 /*-----------------------------------------------------------------*/
7376 /* genDataPointerSet - remat pointer to data space */
7377 /*-----------------------------------------------------------------*/
7379 genDataPointerSet (operand * right,
7383 int size, offset = 0;
7384 char *l, buffer[256];
7386 aopOp (right, ic, FALSE);
7388 l = aopGet (AOP (result), 0, FALSE, TRUE);
7389 size = AOP_SIZE (right);
7393 sprintf (buffer, "(%s + %d)", l + 1, offset);
7395 sprintf (buffer, "%s", l + 1);
7396 emitcode ("mov", "%s,%s", buffer,
7397 aopGet (AOP (right), offset++, FALSE, FALSE));
7400 freeAsmop (right, NULL, ic, TRUE);
7401 freeAsmop (result, NULL, ic, TRUE);
7404 /*-----------------------------------------------------------------*/
7405 /* genNearPointerSet - emitcode for near pointer put */
7406 /*-----------------------------------------------------------------*/
7408 genNearPointerSet (operand * right,
7415 sym_link *retype, *letype;
7416 sym_link *ptype = operandType (result);
7418 retype = getSpec (operandType (right));
7419 letype = getSpec (ptype);
7420 aopOp (result, ic, FALSE);
7422 /* if the result is rematerializable &
7423 in data space & not a bit variable */
7424 if (AOP_TYPE (result) == AOP_IMMD &&
7425 DCL_TYPE (ptype) == POINTER &&
7426 !IS_BITVAR (retype) &&
7427 !IS_BITVAR (letype))
7429 genDataPointerSet (right, result, ic);
7433 /* if the value is already in a pointer register
7434 then don't need anything more */
7435 if (!AOP_INPREG (AOP (result)))
7437 /* otherwise get a free pointer register */
7439 preg = getFreePtr (ic, &aop, FALSE);
7440 emitcode ("mov", "%s,%s",
7442 aopGet (AOP (result), 0, FALSE, TRUE));
7446 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7448 freeAsmop (result, NULL, ic, TRUE);
7449 aopOp (right, ic, FALSE);
7451 /* if bitfield then unpack the bits */
7452 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7453 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7456 /* we have can just get the values */
7457 int size = AOP_SIZE (right);
7462 l = aopGet (AOP (right), offset, FALSE, TRUE);
7466 emitcode ("mov", "@%s,a", rname);
7469 emitcode ("mov", "@%s,%s", rname, l);
7471 emitcode ("inc", "%s", rname);
7476 /* now some housekeeping stuff */
7479 /* we had to allocate for this iCode */
7480 freeAsmop (NULL, aop, ic, TRUE);
7484 /* we did not allocate which means left
7485 already in a pointer register, then
7486 if size > 0 && this could be used again
7487 we have to point it back to where it
7489 if (AOP_SIZE (right) > 1 &&
7490 !OP_SYMBOL (result)->remat &&
7491 (OP_SYMBOL (result)->liveTo > ic->seq ||
7494 int size = AOP_SIZE (right) - 1;
7496 emitcode ("dec", "%s", rname);
7501 freeAsmop (right, NULL, ic, TRUE);
7506 /*-----------------------------------------------------------------*/
7507 /* genPagedPointerSet - emitcode for Paged pointer put */
7508 /*-----------------------------------------------------------------*/
7510 genPagedPointerSet (operand * right,
7517 sym_link *retype, *letype;
7519 retype = getSpec (operandType (right));
7520 letype = getSpec (operandType (result));
7522 aopOp (result, ic, FALSE);
7524 /* if the value is already in a pointer register
7525 then don't need anything more */
7526 if (!AOP_INPREG (AOP (result)))
7528 /* otherwise get a free pointer register */
7530 preg = getFreePtr (ic, &aop, FALSE);
7531 emitcode ("mov", "%s,%s",
7533 aopGet (AOP (result), 0, FALSE, TRUE));
7537 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7539 freeAsmop (result, NULL, ic, TRUE);
7540 aopOp (right, ic, FALSE);
7542 /* if bitfield then unpack the bits */
7543 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7544 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7547 /* we have can just get the values */
7548 int size = AOP_SIZE (right);
7553 l = aopGet (AOP (right), offset, FALSE, TRUE);
7556 emitcode ("movx", "@%s,a", rname);
7559 emitcode ("inc", "%s", rname);
7565 /* now some housekeeping stuff */
7568 /* we had to allocate for this iCode */
7569 freeAsmop (NULL, aop, ic, TRUE);
7573 /* we did not allocate which means left
7574 already in a pointer register, then
7575 if size > 0 && this could be used again
7576 we have to point it back to where it
7578 if (AOP_SIZE (right) > 1 &&
7579 !OP_SYMBOL (result)->remat &&
7580 (OP_SYMBOL (result)->liveTo > ic->seq ||
7583 int size = AOP_SIZE (right) - 1;
7585 emitcode ("dec", "%s", rname);
7590 freeAsmop (right, NULL, ic, TRUE);
7595 /*-----------------------------------------------------------------*/
7596 /* genFarPointerSet - set value from far space */
7597 /*-----------------------------------------------------------------*/
7599 genFarPointerSet (operand * right,
7600 operand * result, iCode * ic)
7603 sym_link *retype = getSpec (operandType (right));
7604 sym_link *letype = getSpec (operandType (result));
7605 aopOp (result, ic, FALSE);
7607 /* if the operand is already in dptr
7608 then we do nothing else we move the value to dptr */
7609 if (AOP_TYPE (result) != AOP_STR)
7611 /* if this is remateriazable */
7612 if (AOP_TYPE (result) == AOP_IMMD)
7613 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7615 { /* we need to get it byte by byte */
7616 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7617 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7620 /* so dptr know contains the address */
7621 freeAsmop (result, NULL, ic, TRUE);
7622 aopOp (right, ic, FALSE);
7624 /* if bit then unpack */
7625 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7626 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7629 size = AOP_SIZE (right);
7634 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7636 emitcode ("movx", "@dptr,a");
7638 emitcode ("inc", "dptr");
7642 freeAsmop (right, NULL, ic, TRUE);
7645 /*-----------------------------------------------------------------*/
7646 /* genGenPointerSet - set value from generic pointer space */
7647 /*-----------------------------------------------------------------*/
7649 genGenPointerSet (operand * right,
7650 operand * result, iCode * ic)
7653 sym_link *retype = getSpec (operandType (right));
7654 sym_link *letype = getSpec (operandType (result));
7656 aopOp (result, ic, FALSE);
7658 /* if the operand is already in dptr
7659 then we do nothing else we move the value to dptr */
7660 if (AOP_TYPE (result) != AOP_STR)
7662 /* if this is remateriazable */
7663 if (AOP_TYPE (result) == AOP_IMMD)
7665 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7666 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7669 { /* we need to get it byte by byte */
7670 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7671 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7672 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7675 /* so dptr know contains the address */
7676 freeAsmop (result, NULL, ic, TRUE);
7677 aopOp (right, ic, FALSE);
7679 /* if bit then unpack */
7680 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7681 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7684 size = AOP_SIZE (right);
7689 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7691 emitcode ("lcall", "__gptrput");
7693 emitcode ("inc", "dptr");
7697 freeAsmop (right, NULL, ic, TRUE);
7700 /*-----------------------------------------------------------------*/
7701 /* genPointerSet - stores the value into a pointer location */
7702 /*-----------------------------------------------------------------*/
7704 genPointerSet (iCode * ic)
7706 operand *right, *result;
7707 sym_link *type, *etype;
7710 right = IC_RIGHT (ic);
7711 result = IC_RESULT (ic);
7713 /* depending on the type of pointer we need to
7714 move it to the correct pointer register */
7715 type = operandType (result);
7716 etype = getSpec (type);
7717 /* if left is of type of pointer then it is simple */
7718 if (IS_PTR (type) && !IS_FUNC (type->next))
7720 p_type = DCL_TYPE (type);
7724 /* we have to go by the storage class */
7725 p_type = PTR_TYPE (SPEC_OCLS (etype));
7728 /* now that we have the pointer type we assign
7729 the pointer values */
7735 genNearPointerSet (right, result, ic);
7739 genPagedPointerSet (right, result, ic);
7743 genFarPointerSet (right, result, ic);
7747 genGenPointerSet (right, result, ic);
7753 /*-----------------------------------------------------------------*/
7754 /* genIfx - generate code for Ifx statement */
7755 /*-----------------------------------------------------------------*/
7757 genIfx (iCode * ic, iCode * popIc)
7759 operand *cond = IC_COND (ic);
7762 aopOp (cond, ic, FALSE);
7764 /* get the value into acc */
7765 if (AOP_TYPE (cond) != AOP_CRY)
7769 /* the result is now in the accumulator */
7770 freeAsmop (cond, NULL, ic, TRUE);
7772 /* if there was something to be popped then do it */
7776 /* if the condition is a bit variable */
7777 if (isbit && IS_ITEMP (cond) &&
7779 genIfxJump (ic, SPIL_LOC (cond)->rname);
7780 else if (isbit && !IS_ITEMP (cond))
7781 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7783 genIfxJump (ic, "a");
7788 /*-----------------------------------------------------------------*/
7789 /* genAddrOf - generates code for address of */
7790 /*-----------------------------------------------------------------*/
7792 genAddrOf (iCode * ic)
7794 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7797 aopOp (IC_RESULT (ic), ic, FALSE);
7799 /* if the operand is on the stack then we
7800 need to get the stack offset of this
7804 /* if it has an offset then we need to compute
7808 emitcode ("mov", "a,_bp");
7809 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7810 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7814 /* we can just move _bp */
7815 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7817 /* fill the result with zero */
7818 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7823 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7829 /* object not on stack then we need the name */
7830 size = AOP_SIZE (IC_RESULT (ic));
7835 char s[SDCC_NAME_MAX];
7837 sprintf (s, "#(%s >> %d)",
7841 sprintf (s, "#%s", sym->rname);
7842 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7846 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7850 /*-----------------------------------------------------------------*/
7851 /* genFarFarAssign - assignment when both are in far space */
7852 /*-----------------------------------------------------------------*/
7854 genFarFarAssign (operand * result, operand * right, iCode * ic)
7856 int size = AOP_SIZE (right);
7859 /* first push the right side on to the stack */
7862 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7864 emitcode ("push", "acc");
7867 freeAsmop (right, NULL, ic, FALSE);
7868 /* now assign DPTR to result */
7869 aopOp (result, ic, FALSE);
7870 size = AOP_SIZE (result);
7873 emitcode ("pop", "acc");
7874 aopPut (AOP (result), "a", --offset);
7876 freeAsmop (result, NULL, ic, FALSE);
7880 /*-----------------------------------------------------------------*/
7881 /* genAssign - generate code for assignment */
7882 /*-----------------------------------------------------------------*/
7884 genAssign (iCode * ic)
7886 operand *result, *right;
7888 unsigned long lit = 0L;
7890 result = IC_RESULT (ic);
7891 right = IC_RIGHT (ic);
7893 /* if they are the same */
7894 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7897 aopOp (right, ic, FALSE);
7899 /* special case both in far space */
7900 if ((AOP_TYPE (right) == AOP_DPTR ||
7901 AOP_TYPE (right) == AOP_DPTR2) &&
7902 IS_TRUE_SYMOP (result) &&
7903 isOperandInFarSpace (result))
7906 genFarFarAssign (result, right, ic);
7910 aopOp (result, ic, TRUE);
7912 /* if they are the same registers */
7913 if (sameRegs (AOP (right), AOP (result)))
7916 /* if the result is a bit */
7917 if (AOP_TYPE (result) == AOP_CRY)
7920 /* if the right size is a literal then
7921 we know what the value is */
7922 if (AOP_TYPE (right) == AOP_LIT)
7924 if (((int) operandLitValue (right)))
7925 aopPut (AOP (result), one, 0);
7927 aopPut (AOP (result), zero, 0);
7931 /* the right is also a bit variable */
7932 if (AOP_TYPE (right) == AOP_CRY)
7934 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7935 aopPut (AOP (result), "c", 0);
7941 aopPut (AOP (result), "a", 0);
7945 /* bit variables done */
7947 size = AOP_SIZE (result);
7949 if (AOP_TYPE (right) == AOP_LIT)
7950 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7952 (AOP_TYPE (result) != AOP_REG) &&
7953 (AOP_TYPE (right) == AOP_LIT) &&
7954 !IS_FLOAT (operandType (right)) &&
7957 emitcode ("clr", "a");
7960 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7961 aopPut (AOP (result), "a", size);
7963 aopPut (AOP (result),
7964 aopGet (AOP (right), size, FALSE, FALSE),
7972 aopPut (AOP (result),
7973 aopGet (AOP (right), offset, FALSE, FALSE),
7980 freeAsmop (right, NULL, ic, TRUE);
7981 freeAsmop (result, NULL, ic, TRUE);
7984 /*-----------------------------------------------------------------*/
7985 /* genJumpTab - genrates code for jump table */
7986 /*-----------------------------------------------------------------*/
7988 genJumpTab (iCode * ic)
7993 aopOp (IC_JTCOND (ic), ic, FALSE);
7994 /* get the condition into accumulator */
7995 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7997 /* multiply by three */
7998 emitcode ("add", "a,acc");
7999 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8000 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8002 jtab = newiTempLabel (NULL);
8003 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8004 emitcode ("jmp", "@a+dptr");
8005 emitcode ("", "%05d$:", jtab->key + 100);
8006 /* now generate the jump labels */
8007 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8008 jtab = setNextItem (IC_JTLABELS (ic)))
8009 emitcode ("ljmp", "%05d$", jtab->key + 100);
8013 /*-----------------------------------------------------------------*/
8014 /* genCast - gen code for casting */
8015 /*-----------------------------------------------------------------*/
8017 genCast (iCode * ic)
8019 operand *result = IC_RESULT (ic);
8020 sym_link *ctype = operandType (IC_LEFT (ic));
8021 sym_link *rtype = operandType (IC_RIGHT (ic));
8022 operand *right = IC_RIGHT (ic);
8025 /* if they are equivalent then do nothing */
8026 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8029 aopOp (right, ic, FALSE);
8030 aopOp (result, ic, FALSE);
8032 /* if the result is a bit */
8033 if (AOP_TYPE (result) == AOP_CRY)
8035 /* if the right size is a literal then
8036 we know what the value is */
8037 if (AOP_TYPE (right) == AOP_LIT)
8039 if (((int) operandLitValue (right)))
8040 aopPut (AOP (result), one, 0);
8042 aopPut (AOP (result), zero, 0);
8047 /* the right is also a bit variable */
8048 if (AOP_TYPE (right) == AOP_CRY)
8050 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8051 aopPut (AOP (result), "c", 0);
8057 aopPut (AOP (result), "a", 0);
8061 /* if they are the same size : or less */
8062 if (AOP_SIZE (result) <= AOP_SIZE (right))
8065 /* if they are in the same place */
8066 if (sameRegs (AOP (right), AOP (result)))
8069 /* if they in different places then copy */
8070 size = AOP_SIZE (result);
8074 aopPut (AOP (result),
8075 aopGet (AOP (right), offset, FALSE, FALSE),
8083 /* if the result is of type pointer */
8088 sym_link *type = operandType (right);
8089 sym_link *etype = getSpec (type);
8091 /* pointer to generic pointer */
8092 if (IS_GENPTR (ctype))
8097 p_type = DCL_TYPE (type);
8100 /* we have to go by the storage class */
8101 p_type = PTR_TYPE (SPEC_OCLS (etype));
8104 /* the first two bytes are known */
8105 size = GPTRSIZE - 1;
8109 aopPut (AOP (result),
8110 aopGet (AOP (right), offset, FALSE, FALSE),
8114 /* the last byte depending on type */
8132 /* this should never happen */
8133 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8134 "got unknown pointer type");
8137 aopPut (AOP (result), l, GPTRSIZE - 1);
8141 /* just copy the pointers */
8142 size = AOP_SIZE (result);
8146 aopPut (AOP (result),
8147 aopGet (AOP (right), offset, FALSE, FALSE),
8154 /* so we now know that the size of destination is greater
8155 than the size of the source */
8156 /* we move to result for the size of source */
8157 size = AOP_SIZE (right);
8161 aopPut (AOP (result),
8162 aopGet (AOP (right), offset, FALSE, FALSE),
8167 /* now depending on the sign of the source && destination */
8168 size = AOP_SIZE (result) - AOP_SIZE (right);
8169 /* if unsigned or not an integral type */
8170 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8173 aopPut (AOP (result), zero, offset++);
8177 /* we need to extend the sign :{ */
8178 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8181 emitcode ("rlc", "a");
8182 emitcode ("subb", "a,acc");
8184 aopPut (AOP (result), "a", offset++);
8187 /* we are done hurray !!!! */
8190 freeAsmop (right, NULL, ic, TRUE);
8191 freeAsmop (result, NULL, ic, TRUE);
8195 /*-----------------------------------------------------------------*/
8196 /* genDjnz - generate decrement & jump if not zero instrucion */
8197 /*-----------------------------------------------------------------*/
8199 genDjnz (iCode * ic, iCode * ifx)
8205 /* if the if condition has a false label
8206 then we cannot save */
8210 /* if the minus is not of the form
8212 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8213 !IS_OP_LITERAL (IC_RIGHT (ic)))
8216 if (operandLitValue (IC_RIGHT (ic)) != 1)
8219 /* if the size of this greater than one then no
8221 if (getSize (operandType (IC_RESULT (ic))) > 1)
8224 /* otherwise we can save BIG */
8225 lbl = newiTempLabel (NULL);
8226 lbl1 = newiTempLabel (NULL);
8228 aopOp (IC_RESULT (ic), ic, FALSE);
8230 if (IS_AOP_PREG (IC_RESULT (ic)))
8232 emitcode ("dec", "%s",
8233 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8234 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8235 emitcode ("jnz", "%05d$", lbl->key + 100);
8239 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8242 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8243 emitcode ("", "%05d$:", lbl->key + 100);
8244 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8245 emitcode ("", "%05d$:", lbl1->key + 100);
8247 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8252 /*-----------------------------------------------------------------*/
8253 /* genReceive - generate code for a receive iCode */
8254 /*-----------------------------------------------------------------*/
8256 genReceive (iCode * ic)
8258 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8259 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8260 IS_TRUE_SYMOP (IC_RESULT (ic))))
8263 int size = getSize (operandType (IC_RESULT (ic)));
8264 int offset = fReturnSizeMCS51 - size;
8267 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8268 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8271 aopOp (IC_RESULT (ic), ic, FALSE);
8272 size = AOP_SIZE (IC_RESULT (ic));
8276 emitcode ("pop", "acc");
8277 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8284 aopOp (IC_RESULT (ic), ic, FALSE);
8286 assignResultValue (IC_RESULT (ic));
8289 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8292 /*-----------------------------------------------------------------*/
8293 /* gen51Code - generate code for 8051 based controllers */
8294 /*-----------------------------------------------------------------*/
8296 gen51Code (iCode * lic)
8301 lineHead = lineCurr = NULL;
8303 /* print the allocation information */
8305 printAllocInfo (currFunc, codeOutFile);
8306 /* if debug information required */
8307 /* if (options.debug && currFunc) { */
8310 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8312 if (IS_STATIC (currFunc->etype))
8313 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8315 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8318 /* stack pointer name */
8319 if (options.useXstack)
8325 for (ic = lic; ic; ic = ic->next)
8328 if (cln != ic->lineno)
8333 emitcode ("", "C$%s$%d$%d$%d ==.",
8334 FileBaseName (ic->filename), ic->lineno,
8335 ic->level, ic->block);
8338 emitcode (";", "%s %d", ic->filename, ic->lineno);
8341 /* if the result is marked as
8342 spilt and rematerializable or code for
8343 this has already been generated then
8345 if (resultRemat (ic) || ic->generated)
8348 /* depending on the operation */
8368 /* IPOP happens only when trying to restore a
8369 spilt live range, if there is an ifx statement
8370 following this pop then the if statement might
8371 be using some of the registers being popped which
8372 would destory the contents of the register so
8373 we need to check for this condition and handle it */
8375 ic->next->op == IFX &&
8376 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8377 genIfx (ic->next, ic);
8395 genEndFunction (ic);
8415 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8432 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8436 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8443 /* note these two are xlated by algebraic equivalence
8444 during parsing SDCC.y */
8445 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8446 "got '>=' or '<=' shouldn't have come here");
8450 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8462 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8466 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8470 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8497 case GET_VALUE_AT_ADDRESS:
8502 if (POINTER_SET (ic))
8529 addSet (&_G.sendSet, ic);
8534 /* piCode(ic,stdout); */
8540 /* now we are ready to call the
8541 peep hole optimizer */
8542 if (!options.nopeep)
8543 peepHole (&lineHead);
8545 /* now do the actual printing */
8546 printLine (lineHead, codeOutFile);