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 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 static char *rb1regs[] = {
97 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
104 #define RESULTONSTACK(x) \
105 (IC_RESULT(x) && IC_RESULT(x)->aop && \
106 IC_RESULT(x)->aop->type == AOP_STK )
108 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
109 #define CLRC emitcode("clr","c")
110 #define SETC emitcode("setb","c")
112 static lineNode *lineHead = NULL;
113 static lineNode *lineCurr = NULL;
115 static unsigned char SLMask[] =
116 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char SRMask[] =
119 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
120 0x07, 0x03, 0x01, 0x00};
127 /*-----------------------------------------------------------------*/
128 /* emitcode - writes the code into a file : for now it is simple */
129 /*-----------------------------------------------------------------*/
131 emitcode (char *inst, char *fmt,...)
134 char lb[INITIAL_INLINEASM];
142 sprintf (lb, "%s\t", inst);
144 sprintf (lb, "%s", inst);
145 vsprintf (lb + (strlen (lb)), fmt, ap);
148 vsprintf (lb, fmt, ap);
150 while (isspace (*lbp))
154 lineCurr = (lineCurr ?
155 connectLine (lineCurr, newLineNode (lb)) :
156 (lineHead = newLineNode (lb)));
157 lineCurr->isInline = _G.inLine;
158 lineCurr->isDebug = _G.debugLine;
162 /*-----------------------------------------------------------------*/
163 /* mova - moves specified value into accumulator */
164 /*-----------------------------------------------------------------*/
168 /* do some early peephole optimization */
169 if (!strcmp(x, "a") || !strcmp(x, "acc"))
172 emitcode("mov","a,%s", x);
175 /*-----------------------------------------------------------------*/
176 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
177 /*-----------------------------------------------------------------*/
179 getFreePtr (iCode * ic, asmop ** aopp, bool result)
181 bool r0iu = FALSE, r1iu = FALSE;
182 bool r0ou = FALSE, r1ou = FALSE;
184 /* the logic: if r0 & r1 used in the instruction
185 then we are in trouble otherwise */
187 /* first check if r0 & r1 are used by this
188 instruction, in which case we are in trouble */
189 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
190 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
195 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
196 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
198 /* if no usage of r0 then return it */
201 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
202 (*aopp)->type = AOP_R0;
204 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
207 /* if no usage of r1 then return it */
210 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
211 (*aopp)->type = AOP_R1;
213 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
216 /* now we know they both have usage */
217 /* if r0 not used in this instruction */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 mcs51_regWithIdx (R0_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
229 (*aopp)->type = AOP_R0;
231 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
234 /* if r1 not used then */
238 /* push it if not already pushed */
241 emitcode ("push", "%s",
242 mcs51_regWithIdx (R1_IDX)->dname);
246 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
247 (*aopp)->type = AOP_R1;
248 return mcs51_regWithIdx (R1_IDX);
252 /* I said end of world but not quite end of world yet */
253 /* if this is a result then we can push it on the stack */
256 (*aopp)->type = AOP_STK;
260 /* other wise this is true end of the world */
261 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
262 "getFreePtr should never reach here");
266 /*-----------------------------------------------------------------*/
267 /* newAsmop - creates a new asmOp */
268 /*-----------------------------------------------------------------*/
270 newAsmop (short type)
274 aop = Safe_calloc (1, sizeof (asmop));
279 /*-----------------------------------------------------------------*/
280 /* pointerCode - returns the code for a pointer type */
281 /*-----------------------------------------------------------------*/
283 pointerCode (sym_link * etype)
286 return PTR_TYPE (SPEC_OCLS (etype));
290 /*-----------------------------------------------------------------*/
291 /* aopForSym - for a true symbol */
292 /*-----------------------------------------------------------------*/
294 aopForSym (iCode * ic, symbol * sym, bool result)
299 wassertl (ic != NULL, "Got a null iCode");
300 wassertl (sym != NULL, "Got a null symbol");
302 space = SPEC_OCLS (sym->etype);
304 /* if already has one */
308 /* assign depending on the storage class */
309 /* if it is on the stack or indirectly addressable */
310 /* space we need to assign either r0 or r1 to it */
311 if (sym->onStack || sym->iaccess)
313 sym->aop = aop = newAsmop (0);
314 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
315 aop->size = getSize (sym->type);
317 /* now assign the address of the variable to
318 the pointer register */
319 if (aop->type != AOP_STK)
325 emitcode ("push", "acc");
327 emitcode ("mov", "a,_bp");
328 emitcode ("add", "a,#0x%02x",
330 ((char) (sym->stack - _G.nRegsSaved)) :
331 ((char) sym->stack)) & 0xff);
332 emitcode ("mov", "%s,a",
333 aop->aopu.aop_ptr->name);
336 emitcode ("pop", "acc");
339 emitcode ("mov", "%s,#%s",
340 aop->aopu.aop_ptr->name,
342 aop->paged = space->paged;
345 aop->aopu.aop_stk = sym->stack;
349 /* if in bit space */
350 if (IN_BITSPACE (space))
352 sym->aop = aop = newAsmop (AOP_CRY);
353 aop->aopu.aop_dir = sym->rname;
354 aop->size = getSize (sym->type);
357 /* if it is in direct space */
358 if (IN_DIRSPACE (space))
360 sym->aop = aop = newAsmop (AOP_DIR);
361 aop->aopu.aop_dir = sym->rname;
362 aop->size = getSize (sym->type);
366 /* special case for a function */
367 if (IS_FUNC (sym->type))
369 sym->aop = aop = newAsmop (AOP_IMMD);
370 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
371 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop (AOP_DPTR);
379 emitcode ("mov", "dptr,#%s", sym->rname);
380 aop->size = getSize (sym->type);
382 /* if it is in code space */
383 if (IN_CODESPACE (space))
389 /*-----------------------------------------------------------------*/
390 /* aopForRemat - rematerialzes an object */
391 /*-----------------------------------------------------------------*/
393 aopForRemat (symbol * sym)
395 iCode *ic = sym->rematiCode;
396 asmop *aop = newAsmop (AOP_IMMD);
403 val += (int) operandLitValue (IC_RIGHT (ic));
404 else if (ic->op == '-')
405 val -= (int) operandLitValue (IC_RIGHT (ic));
406 else if (IS_CAST_ICODE(ic)) {
407 sym_link *from_type = operandType(IC_RIGHT(ic));
408 aop->aopu.aop_immd.from_cast_remat = 1;
409 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
410 ptr_type = DCL_TYPE(from_type);
411 if (ptr_type == IPOINTER) {
418 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
422 sprintf (buffer, "(%s %c 0x%04x)",
423 OP_SYMBOL (IC_LEFT (ic))->rname,
424 val >= 0 ? '+' : '-',
427 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
429 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
430 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
431 /* set immd2 field if required */
432 if (aop->aopu.aop_immd.from_cast_remat) {
433 sprintf(buffer,"#0x%02x",ptr_type);
434 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
435 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
441 /*-----------------------------------------------------------------*/
442 /* regsInCommon - two operands have some registers in common */
443 /*-----------------------------------------------------------------*/
445 regsInCommon (operand * op1, operand * op2)
450 /* if they have registers in common */
451 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
454 sym1 = OP_SYMBOL (op1);
455 sym2 = OP_SYMBOL (op2);
457 if (sym1->nRegs == 0 || sym2->nRegs == 0)
460 for (i = 0; i < sym1->nRegs; i++)
466 for (j = 0; j < sym2->nRegs; j++)
471 if (sym2->regs[j] == sym1->regs[i])
479 /*-----------------------------------------------------------------*/
480 /* operandsEqu - equivalent */
481 /*-----------------------------------------------------------------*/
483 operandsEqu (operand * op1, operand * op2)
487 /* if they not symbols */
488 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
491 sym1 = OP_SYMBOL (op1);
492 sym2 = OP_SYMBOL (op2);
494 /* if both are itemps & one is spilt
495 and the other is not then false */
496 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
497 sym1->isspilt != sym2->isspilt)
500 /* if they are the same */
504 if (strcmp (sym1->rname, sym2->rname) == 0)
508 /* if left is a tmp & right is not */
509 if (IS_ITEMP (op1) &&
512 (sym1->usl.spillLoc == sym2))
515 if (IS_ITEMP (op2) &&
519 (sym2->usl.spillLoc == sym1))
525 /*-----------------------------------------------------------------*/
526 /* sameRegs - two asmops have the same registers */
527 /*-----------------------------------------------------------------*/
529 sameRegs (asmop * aop1, asmop * aop2)
536 if (aop1->type != AOP_REG ||
537 aop2->type != AOP_REG)
540 if (aop1->size != aop2->size)
543 for (i = 0; i < aop1->size; i++)
544 if (aop1->aopu.aop_reg[i] !=
545 aop2->aopu.aop_reg[i])
551 /*-----------------------------------------------------------------*/
552 /* aopOp - allocates an asmop for an operand : */
553 /*-----------------------------------------------------------------*/
555 aopOp (operand * op, iCode * ic, bool result)
564 /* if this a literal */
565 if (IS_OP_LITERAL (op))
567 op->aop = aop = newAsmop (AOP_LIT);
568 aop->aopu.aop_lit = op->operand.valOperand;
569 aop->size = getSize (operandType (op));
573 /* if already has a asmop then continue */
577 /* if the underlying symbol has a aop */
578 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
580 op->aop = OP_SYMBOL (op)->aop;
584 /* if this is a true symbol */
585 if (IS_TRUE_SYMOP (op))
587 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
591 /* this is a temporary : this has
597 e) can be a return use only */
599 sym = OP_SYMBOL (op);
601 /* if the type is a conditional */
602 if (sym->regType == REG_CND)
604 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
609 /* if it is spilt then two situations
611 b) has a spill location */
612 if (sym->isspilt || sym->nRegs == 0)
615 /* rematerialize it NOW */
618 sym->aop = op->aop = aop =
620 aop->size = getSize (sym->type);
627 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
628 aop->size = getSize (sym->type);
629 for (i = 0; i < 2; i++)
630 aop->aopu.aop_str[i] = accUse[i];
638 aop = op->aop = sym->aop = newAsmop (AOP_STR);
639 aop->size = getSize (sym->type);
640 for (i = 0; i < fReturnSizeMCS51; i++)
641 aop->aopu.aop_str[i] = fReturn[i];
645 /* else spill location */
646 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
647 /* force a new aop if sizes differ */
648 sym->usl.spillLoc->aop = NULL;
650 sym->aop = op->aop = aop =
651 aopForSym (ic, sym->usl.spillLoc, result);
652 aop->size = getSize (sym->type);
656 /* must be in a register */
657 sym->aop = op->aop = aop = newAsmop (AOP_REG);
658 aop->size = sym->nRegs;
659 for (i = 0; i < sym->nRegs; i++)
660 aop->aopu.aop_reg[i] = sym->regs[i];
663 /*-----------------------------------------------------------------*/
664 /* freeAsmop - free up the asmop given to an operand */
665 /*----------------------------------------------------------------*/
667 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
684 /* depending on the asmop type only three cases need work AOP_RO
685 , AOP_R1 && AOP_STK */
693 emitcode ("pop", "ar0");
697 bitVectUnSetBit (ic->rUsed, R0_IDX);
705 emitcode ("pop", "ar1");
709 bitVectUnSetBit (ic->rUsed, R1_IDX);
715 int stk = aop->aopu.aop_stk + aop->size;
716 bitVectUnSetBit (ic->rUsed, R0_IDX);
717 bitVectUnSetBit (ic->rUsed, R1_IDX);
719 getFreePtr (ic, &aop, FALSE);
723 emitcode ("mov", "a,_bp");
724 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
725 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
729 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
734 emitcode ("pop", "acc");
735 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
738 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
741 freeAsmop (op, NULL, ic, TRUE);
744 emitcode ("pop", "ar0");
750 emitcode ("pop", "ar1");
757 /* all other cases just dealloc */
763 OP_SYMBOL (op)->aop = NULL;
764 /* if the symbol has a spill */
766 SPIL_LOC (op)->aop = NULL;
771 /*-----------------------------------------------------------------*/
772 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
773 /* clobber the accumulator */
774 /*-----------------------------------------------------------------*/
776 aopGetUsesAcc (asmop *aop, int offset)
778 if (offset > (aop->size - 1))
795 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
804 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
808 /* Error case --- will have been caught already */
815 /*-----------------------------------------------------------------*/
816 /* aopGet - for fetching value of the aop */
817 /*-----------------------------------------------------------------*/
819 aopGet (asmop * aop, int offset, bool bit16, bool dname)
824 /* offset is greater than
826 if (offset > (aop->size - 1) &&
827 aop->type != AOP_LIT)
830 /* depending on type */
836 /* if we need to increment it */
837 while (offset > aop->coff)
839 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
843 while (offset < aop->coff)
845 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
852 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
853 return (dname ? "acc" : "a");
855 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
856 rs = Safe_calloc (1, strlen (s) + 1);
861 while (offset > aop->coff)
863 emitcode ("inc", "dptr");
867 while (offset < aop->coff)
869 emitcode ("lcall", "__decdptr");
876 emitcode ("clr", "a");
877 emitcode ("movc", "a,@a+dptr");
881 emitcode ("movx", "a,@dptr");
883 return (dname ? "acc" : "a");
887 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
888 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
890 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
892 sprintf (s, "#(%s >> %d)",
893 aop->aopu.aop_immd.aop_immd1,
897 aop->aopu.aop_immd.aop_immd1);
898 rs = Safe_calloc (1, strlen (s) + 1);
904 sprintf (s, "(%s + %d)",
908 sprintf (s, "%s", aop->aopu.aop_dir);
909 rs = Safe_calloc (1, strlen (s) + 1);
915 return aop->aopu.aop_reg[offset]->dname;
917 return aop->aopu.aop_reg[offset]->name;
920 emitcode ("clr", "a");
921 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
922 emitcode ("rlc", "a");
923 return (dname ? "acc" : "a");
926 if (!offset && dname)
928 return aop->aopu.aop_str[offset];
931 return aopLiteral (aop->aopu.aop_lit, offset);
935 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
939 return aop->aopu.aop_str[offset];
943 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
944 "aopget got unsupported aop->type");
947 /*-----------------------------------------------------------------*/
948 /* aopPut - puts a string for a aop */
949 /*-----------------------------------------------------------------*/
951 aopPut (asmop * aop, char *s, int offset)
955 if (aop->size && offset > (aop->size - 1))
957 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
958 "aopPut got offset > aop->size");
962 /* will assign value to value */
963 /* depending on where it is ofcourse */
968 sprintf (d, "(%s + %d)",
969 aop->aopu.aop_dir, offset);
971 sprintf (d, "%s", aop->aopu.aop_dir);
974 emitcode ("mov", "%s,%s", d, s);
979 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
980 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
983 strcmp (s, "r0") == 0 ||
984 strcmp (s, "r1") == 0 ||
985 strcmp (s, "r2") == 0 ||
986 strcmp (s, "r3") == 0 ||
987 strcmp (s, "r4") == 0 ||
988 strcmp (s, "r5") == 0 ||
989 strcmp (s, "r6") == 0 ||
990 strcmp (s, "r7") == 0)
991 emitcode ("mov", "%s,%s",
992 aop->aopu.aop_reg[offset]->dname, s);
994 emitcode ("mov", "%s,%s",
995 aop->aopu.aop_reg[offset]->name, s);
1002 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1003 "aopPut writting to code space");
1007 while (offset > aop->coff)
1010 emitcode ("inc", "dptr");
1013 while (offset < aop->coff)
1016 emitcode ("lcall", "__decdptr");
1021 /* if not in accumulater */
1024 emitcode ("movx", "@dptr,a");
1029 while (offset > aop->coff)
1032 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1034 while (offset < aop->coff)
1037 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1044 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1050 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1052 else if (strcmp (s, "r0") == 0 ||
1053 strcmp (s, "r1") == 0 ||
1054 strcmp (s, "r2") == 0 ||
1055 strcmp (s, "r3") == 0 ||
1056 strcmp (s, "r4") == 0 ||
1057 strcmp (s, "r5") == 0 ||
1058 strcmp (s, "r6") == 0 ||
1059 strcmp (s, "r7") == 0)
1062 sprintf (buffer, "a%s", s);
1063 emitcode ("mov", "@%s,%s",
1064 aop->aopu.aop_ptr->name, buffer);
1067 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1072 if (strcmp (s, "a") == 0)
1073 emitcode ("push", "acc");
1077 emitcode ("push", "acc");
1079 emitcode ("push", s);
1085 /* if bit variable */
1086 if (!aop->aopu.aop_dir)
1088 emitcode ("clr", "a");
1089 emitcode ("rlc", "a");
1094 emitcode ("clr", "%s", aop->aopu.aop_dir);
1096 emitcode ("setb", "%s", aop->aopu.aop_dir);
1097 else if (!strcmp (s, "c"))
1098 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1101 if (strcmp (s, "a"))
1106 /* set C, if a >= 1 */
1107 emitcode ("add", "a,#0xff");
1108 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1116 if (strcmp (aop->aopu.aop_str[offset], s))
1117 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1122 if (!offset && (strcmp (s, "acc") == 0))
1125 if (strcmp (aop->aopu.aop_str[offset], s))
1126 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1130 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1131 "aopPut got unsupported aop->type");
1139 /*-----------------------------------------------------------------*/
1140 /* pointToEnd :- points to the last byte of the operand */
1141 /*-----------------------------------------------------------------*/
1143 pointToEnd (asmop * aop)
1149 aop->coff = count = (aop->size - 1);
1155 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1159 emitcode ("inc", "dptr");
1166 /*-----------------------------------------------------------------*/
1167 /* reAdjustPreg - points a register back to where it should */
1168 /*-----------------------------------------------------------------*/
1170 reAdjustPreg (asmop * aop)
1172 if ((aop->coff==0) || aop->size <= 1)
1180 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("lcall", "__decdptr");
1192 #define AOP(op) op->aop
1193 #define AOP_TYPE(op) AOP(op)->type
1194 #define AOP_SIZE(op) AOP(op)->size
1195 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1196 AOP_TYPE(x) == AOP_R0))
1198 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1199 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1201 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1202 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1203 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1205 /*-----------------------------------------------------------------*/
1206 /* genNotFloat - generates not for float operations */
1207 /*-----------------------------------------------------------------*/
1209 genNotFloat (operand * op, operand * res)
1215 D(emitcode (";", "genNotFloat"));
1217 /* we will put 127 in the first byte of
1219 aopPut (AOP (res), "#127", 0);
1220 size = AOP_SIZE (op) - 1;
1223 l = aopGet (op->aop, offset++, FALSE, FALSE);
1228 emitcode ("orl", "a,%s",
1230 offset++, FALSE, FALSE));
1233 tlbl = newiTempLabel (NULL);
1234 aopPut (res->aop, one, 1);
1235 emitcode ("jz", "%05d$", (tlbl->key + 100));
1236 aopPut (res->aop, zero, 1);
1237 emitcode ("", "%05d$:", (tlbl->key + 100));
1239 size = res->aop->size - 2;
1241 /* put zeros in the rest */
1243 aopPut (res->aop, zero, offset++);
1246 /*-----------------------------------------------------------------*/
1247 /* opIsGptr: returns non-zero if the passed operand is */
1248 /* a generic pointer type. */
1249 /*-----------------------------------------------------------------*/
1251 opIsGptr (operand * op)
1253 sym_link *type = operandType (op);
1255 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1262 /*-----------------------------------------------------------------*/
1263 /* getDataSize - get the operand data size */
1264 /*-----------------------------------------------------------------*/
1266 getDataSize (operand * op)
1269 size = AOP_SIZE (op);
1270 if (size == GPTRSIZE)
1272 sym_link *type = operandType (op);
1273 if (IS_GENPTR (type))
1275 /* generic pointer; arithmetic operations
1276 * should ignore the high byte (pointer type).
1284 /*-----------------------------------------------------------------*/
1285 /* outAcc - output Acc */
1286 /*-----------------------------------------------------------------*/
1288 outAcc (operand * result)
1291 size = getDataSize (result);
1294 aopPut (AOP (result), "a", 0);
1297 /* unsigned or positive */
1300 aopPut (AOP (result), zero, offset++);
1305 /*-----------------------------------------------------------------*/
1306 /* outBitC - output a bit C */
1307 /*-----------------------------------------------------------------*/
1309 outBitC (operand * result)
1311 /* if the result is bit */
1312 if (AOP_TYPE (result) == AOP_CRY)
1313 aopPut (AOP (result), "c", 0);
1316 emitcode ("clr", "a");
1317 emitcode ("rlc", "a");
1322 /*-----------------------------------------------------------------*/
1323 /* toBoolean - emit code for orl a,operator(sizeop) */
1324 /*-----------------------------------------------------------------*/
1326 toBoolean (operand * oper)
1328 int size = AOP_SIZE (oper) - 1;
1330 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1332 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1336 /*-----------------------------------------------------------------*/
1337 /* genNot - generate code for ! operation */
1338 /*-----------------------------------------------------------------*/
1343 sym_link *optype = operandType (IC_LEFT (ic));
1345 D(emitcode (";", "genNot"));
1347 /* assign asmOps to operand & result */
1348 aopOp (IC_LEFT (ic), ic, FALSE);
1349 aopOp (IC_RESULT (ic), ic, TRUE);
1351 /* if in bit space then a special case */
1352 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1354 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1355 emitcode ("cpl", "c");
1356 outBitC (IC_RESULT (ic));
1360 /* if type float then do float */
1361 if (IS_FLOAT (optype))
1363 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1367 toBoolean (IC_LEFT (ic));
1369 tlbl = newiTempLabel (NULL);
1370 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1371 emitcode ("", "%05d$:", tlbl->key + 100);
1372 outBitC (IC_RESULT (ic));
1375 /* release the aops */
1376 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1377 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1381 /*-----------------------------------------------------------------*/
1382 /* genCpl - generate code for complement */
1383 /*-----------------------------------------------------------------*/
1391 D(emitcode (";", "genCpl"));
1393 /* assign asmOps to operand & result */
1394 aopOp (IC_LEFT (ic), ic, FALSE);
1395 aopOp (IC_RESULT (ic), ic, TRUE);
1397 /* special case if in bit space */
1398 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1399 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1400 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1401 emitcode ("cpl", "c");
1402 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1405 tlbl=newiTempLabel(NULL);
1406 emitcode ("cjne", "%s,#0x01,%05d$",
1407 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1408 emitcode ("", "%05d$:", tlbl->key+100);
1409 outBitC (IC_RESULT(ic));
1413 size = AOP_SIZE (IC_RESULT (ic));
1416 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1418 emitcode ("cpl", "a");
1419 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1424 /* release the aops */
1425 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1426 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1429 /*-----------------------------------------------------------------*/
1430 /* genUminusFloat - unary minus for floating points */
1431 /*-----------------------------------------------------------------*/
1433 genUminusFloat (operand * op, operand * result)
1435 int size, offset = 0;
1438 D(emitcode (";", "genUminusFloat"));
1440 /* for this we just need to flip the
1441 first it then copy the rest in place */
1442 size = AOP_SIZE (op) - 1;
1443 l = aopGet (AOP (op), 3, FALSE, FALSE);
1447 emitcode ("cpl", "acc.7");
1448 aopPut (AOP (result), "a", 3);
1452 aopPut (AOP (result),
1453 aopGet (AOP (op), offset, FALSE, FALSE),
1459 /*-----------------------------------------------------------------*/
1460 /* genUminus - unary minus code generation */
1461 /*-----------------------------------------------------------------*/
1463 genUminus (iCode * ic)
1466 sym_link *optype, *rtype;
1469 D(emitcode (";", "genUminus"));
1472 aopOp (IC_LEFT (ic), ic, FALSE);
1473 aopOp (IC_RESULT (ic), ic, TRUE);
1475 /* if both in bit space then special
1477 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1478 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1481 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1482 emitcode ("cpl", "c");
1483 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1487 optype = operandType (IC_LEFT (ic));
1488 rtype = operandType (IC_RESULT (ic));
1490 /* if float then do float stuff */
1491 if (IS_FLOAT (optype))
1493 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1497 /* otherwise subtract from zero */
1498 size = AOP_SIZE (IC_LEFT (ic));
1503 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1504 if (!strcmp (l, "a"))
1508 emitcode ("cpl", "a");
1509 emitcode ("addc", "a,#0");
1515 emitcode ("clr", "a");
1516 emitcode ("subb", "a,%s", l);
1518 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1521 /* if any remaining bytes in the result */
1522 /* we just need to propagate the sign */
1523 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1525 emitcode ("rlc", "a");
1526 emitcode ("subb", "a,acc");
1528 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1532 /* release the aops */
1533 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1534 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1537 /*-----------------------------------------------------------------*/
1538 /* saveRegisters - will look for a call and save the registers */
1539 /*-----------------------------------------------------------------*/
1541 saveRegisters (iCode * lic)
1548 for (ic = lic; ic; ic = ic->next)
1549 if (ic->op == CALL || ic->op == PCALL)
1554 fprintf (stderr, "found parameter push with no function call\n");
1558 /* if the registers have been saved already or don't need to be then
1560 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1561 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1564 /* safe the registers in use at this time but skip the
1565 ones for the result */
1566 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1567 mcs51_rUmaskForOp (IC_RESULT(ic)));
1570 if (options.useXstack)
1572 if (bitVectBitValue (rsave, R0_IDX))
1573 emitcode ("mov", "b,r0");
1574 emitcode ("mov", "r0,%s", spname);
1575 for (i = 0; i < mcs51_nRegs; i++)
1577 if (bitVectBitValue (rsave, i))
1580 emitcode ("mov", "a,b");
1582 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1583 emitcode ("movx", "@r0,a");
1584 emitcode ("inc", "r0");
1587 emitcode ("mov", "%s,r0", spname);
1588 if (bitVectBitValue (rsave, R0_IDX))
1589 emitcode ("mov", "r0,b");
1592 for (i = 0; i < mcs51_nRegs; i++)
1594 if (bitVectBitValue (rsave, i))
1595 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1599 /*-----------------------------------------------------------------*/
1600 /* unsaveRegisters - pop the pushed registers */
1601 /*-----------------------------------------------------------------*/
1603 unsaveRegisters (iCode * ic)
1608 /* restore the registers in use at this time but skip the
1609 ones for the result */
1610 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1611 mcs51_rUmaskForOp (IC_RESULT(ic)));
1613 if (options.useXstack)
1615 emitcode ("mov", "r0,%s", spname);
1616 for (i = mcs51_nRegs; i >= 0; i--)
1618 if (bitVectBitValue (rsave, i))
1620 emitcode ("dec", "r0");
1621 emitcode ("movx", "a,@r0");
1623 emitcode ("mov", "b,a");
1625 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1629 emitcode ("mov", "%s,r0", spname);
1630 if (bitVectBitValue (rsave, R0_IDX))
1631 emitcode ("mov", "r0,b");
1634 for (i = mcs51_nRegs; i >= 0; i--)
1636 if (bitVectBitValue (rsave, i))
1637 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1643 /*-----------------------------------------------------------------*/
1645 /*-----------------------------------------------------------------*/
1647 pushSide (operand * oper, int size)
1652 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1653 if (AOP_TYPE (oper) != AOP_REG &&
1654 AOP_TYPE (oper) != AOP_DIR &&
1657 emitcode ("mov", "a,%s", l);
1658 emitcode ("push", "acc");
1661 emitcode ("push", "%s", l);
1665 /*-----------------------------------------------------------------*/
1666 /* assignResultValue - */
1667 /*-----------------------------------------------------------------*/
1669 assignResultValue (operand * oper)
1672 int size = AOP_SIZE (oper);
1675 aopPut (AOP (oper), fReturn[offset], offset);
1681 /*-----------------------------------------------------------------*/
1682 /* genXpush - pushes onto the external stack */
1683 /*-----------------------------------------------------------------*/
1685 genXpush (iCode * ic)
1687 asmop *aop = newAsmop (0);
1689 int size, offset = 0;
1691 D(emitcode (";", "genXpush"));
1693 aopOp (IC_LEFT (ic), ic, FALSE);
1694 r = getFreePtr (ic, &aop, FALSE);
1697 emitcode ("mov", "%s,_spx", r->name);
1699 size = AOP_SIZE (IC_LEFT (ic));
1703 char *l = aopGet (AOP (IC_LEFT (ic)),
1704 offset++, FALSE, FALSE);
1706 emitcode ("movx", "@%s,a", r->name);
1707 emitcode ("inc", "%s", r->name);
1712 emitcode ("mov", "_spx,%s", r->name);
1714 freeAsmop (NULL, aop, ic, TRUE);
1715 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1718 /*-----------------------------------------------------------------*/
1719 /* genIpush - genrate code for pushing this gets a little complex */
1720 /*-----------------------------------------------------------------*/
1722 genIpush (iCode * ic)
1724 int size, offset = 0;
1727 D(emitcode (";", "genIpush"));
1729 /* if this is not a parm push : ie. it is spill push
1730 and spill push is always done on the local stack */
1734 /* and the item is spilt then do nothing */
1735 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1738 aopOp (IC_LEFT (ic), ic, FALSE);
1739 size = AOP_SIZE (IC_LEFT (ic));
1740 /* push it on the stack */
1743 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1749 emitcode ("push", "%s", l);
1754 /* this is a paramter push: in this case we call
1755 the routine to find the call and save those
1756 registers that need to be saved */
1759 /* if use external stack then call the external
1760 stack pushing routine */
1761 if (options.useXstack)
1767 /* then do the push */
1768 aopOp (IC_LEFT (ic), ic, FALSE);
1771 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1772 size = AOP_SIZE (IC_LEFT (ic));
1776 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1777 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1778 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1781 emitcode ("mov", "a,%s", l);
1782 emitcode ("push", "acc");
1785 emitcode ("push", "%s", l);
1788 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1791 /*-----------------------------------------------------------------*/
1792 /* genIpop - recover the registers: can happen only for spilling */
1793 /*-----------------------------------------------------------------*/
1795 genIpop (iCode * ic)
1799 D(emitcode (";", "genIpop"));
1801 /* if the temp was not pushed then */
1802 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1805 aopOp (IC_LEFT (ic), ic, FALSE);
1806 size = AOP_SIZE (IC_LEFT (ic));
1807 offset = (size - 1);
1809 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1812 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1815 /*-----------------------------------------------------------------*/
1816 /* unsaveRBank - restores the resgister bank from stack */
1817 /*-----------------------------------------------------------------*/
1819 unsaveRBank (int bank, iCode * ic, bool popPsw)
1825 if (options.useXstack)
1829 /* Assume r0 is available for use. */
1830 r = mcs51_regWithIdx (R0_IDX);;
1835 r = getFreePtr (ic, &aop, FALSE);
1837 emitcode ("mov", "%s,_spx", r->name);
1842 if (options.useXstack)
1844 emitcode ("movx", "a,@%s", r->name);
1845 emitcode ("mov", "psw,a");
1846 emitcode ("dec", "%s", r->name);
1850 emitcode ("pop", "psw");
1854 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1856 if (options.useXstack)
1858 emitcode ("movx", "a,@%s", r->name);
1859 emitcode ("mov", "(%s+%d),a",
1860 regs8051[i].base, 8 * bank + regs8051[i].offset);
1861 emitcode ("dec", "%s", r->name);
1865 emitcode ("pop", "(%s+%d)",
1866 regs8051[i].base, 8 * bank + regs8051[i].offset);
1869 if (options.useXstack)
1871 emitcode ("mov", "_spx,%s", r->name);
1876 freeAsmop (NULL, aop, ic, TRUE);
1880 /*-----------------------------------------------------------------*/
1881 /* saveRBank - saves an entire register bank on the stack */
1882 /*-----------------------------------------------------------------*/
1884 saveRBank (int bank, iCode * ic, bool pushPsw)
1890 if (options.useXstack)
1894 /* Assume r0 is available for use. */
1895 r = mcs51_regWithIdx (R0_IDX);;
1900 r = getFreePtr (ic, &aop, FALSE);
1902 emitcode ("mov", "%s,_spx", r->name);
1905 for (i = 0; i < mcs51_nRegs; i++)
1907 if (options.useXstack)
1909 emitcode ("inc", "%s", r->name);
1910 emitcode ("mov", "a,(%s+%d)",
1911 regs8051[i].base, 8 * bank + regs8051[i].offset);
1912 emitcode ("movx", "@%s,a", r->name);
1915 emitcode ("push", "(%s+%d)",
1916 regs8051[i].base, 8 * bank + regs8051[i].offset);
1921 if (options.useXstack)
1923 emitcode ("mov", "a,psw");
1924 emitcode ("movx", "@%s,a", r->name);
1925 emitcode ("inc", "%s", r->name);
1926 emitcode ("mov", "_spx,%s", r->name);
1931 emitcode ("push", "psw");
1934 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1939 freeAsmop (NULL, aop, ic, TRUE);
1948 /*-----------------------------------------------------------------*/
1949 /* genSend - gen code for SEND */
1950 /*-----------------------------------------------------------------*/
1951 static void genSend(set *sendSet)
1956 for (sic = setFirstItem (_G.sendSet); sic;
1957 sic = setNextItem (_G.sendSet)) {
1958 int size, offset = 0;
1959 aopOp (IC_LEFT (sic), sic, FALSE);
1960 size = AOP_SIZE (IC_LEFT (sic));
1962 if (sic->argreg == 1) {
1964 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1966 if (strcmp (l, fReturn[offset]))
1967 emitcode ("mov", "%s,%s", fReturn[offset], l);
1973 emitcode ("mov","b1_%d,%s",rb1_count++,
1974 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1977 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1981 /*-----------------------------------------------------------------*/
1982 /* genCall - generates a call statement */
1983 /*-----------------------------------------------------------------*/
1985 genCall (iCode * ic)
1988 // bool restoreBank = FALSE;
1989 bool swapBanks = FALSE;
1991 D(emitcode(";", "genCall"));
1993 dtype = operandType (IC_LEFT (ic));
1994 /* if send set is not empty the assign */
1997 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1998 genSend(reverseSet(_G.sendSet));
2000 genSend(_G.sendSet);
2006 /* if we are calling a not _naked function that is not using
2007 the same register bank then we need to save the
2008 destination registers on the stack */
2009 dtype = operandType (IC_LEFT (ic));
2010 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2011 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2012 !IFFUNC_ISISR (dtype))
2017 /* if caller saves & we have not saved then */
2023 emitcode ("mov", "psw,#0x%02x",
2024 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2028 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2029 OP_SYMBOL (IC_LEFT (ic))->rname :
2030 OP_SYMBOL (IC_LEFT (ic))->name));
2034 emitcode ("mov", "psw,#0x%02x",
2035 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2038 /* if we need assign a result value */
2039 if ((IS_ITEMP (IC_RESULT (ic)) &&
2040 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2041 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2042 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2043 IS_TRUE_SYMOP (IC_RESULT (ic)))
2047 aopOp (IC_RESULT (ic), ic, FALSE);
2050 assignResultValue (IC_RESULT (ic));
2052 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2055 /* adjust the stack for parameters if
2060 if (ic->parmBytes > 3)
2062 emitcode ("mov", "a,%s", spname);
2063 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2064 emitcode ("mov", "%s,a", spname);
2067 for (i = 0; i < ic->parmBytes; i++)
2068 emitcode ("dec", "%s", spname);
2071 /* if we hade saved some registers then unsave them */
2072 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2073 unsaveRegisters (ic);
2075 // /* if register bank was saved then pop them */
2077 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2080 /*-----------------------------------------------------------------*/
2081 /* -10l - generates a call by pointer statement */
2082 /*-----------------------------------------------------------------*/
2084 genPcall (iCode * ic)
2087 symbol *rlbl = newiTempLabel (NULL);
2088 // bool restoreBank=FALSE;
2089 bool swapBanks = FALSE;
2091 D(emitcode(";", "genPCall"));
2093 /* if caller saves & we have not saved then */
2097 /* if we are calling a not _naked function that is not using
2098 the same register bank then we need to save the
2099 destination registers on the stack */
2100 dtype = operandType (IC_LEFT (ic))->next;
2101 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2102 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2103 !IFFUNC_ISISR (dtype))
2105 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2106 // restoreBank=TRUE;
2108 // need caution message to user here
2111 /* push the return address on to the stack */
2112 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2113 emitcode ("push", "acc");
2114 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2115 emitcode ("push", "acc");
2117 /* now push the calling address */
2118 aopOp (IC_LEFT (ic), ic, FALSE);
2120 pushSide (IC_LEFT (ic), FPTRSIZE);
2122 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2124 /* if send set is not empty the assign */
2127 genSend(reverseSet(_G.sendSet));
2133 emitcode ("mov", "psw,#0x%02x",
2134 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2138 emitcode ("ret", "");
2139 emitcode ("", "%05d$:", (rlbl->key + 100));
2144 emitcode ("mov", "psw,#0x%02x",
2145 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2148 /* if we need assign a result value */
2149 if ((IS_ITEMP (IC_RESULT (ic)) &&
2150 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2151 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2152 IS_TRUE_SYMOP (IC_RESULT (ic)))
2156 aopOp (IC_RESULT (ic), ic, FALSE);
2159 assignResultValue (IC_RESULT (ic));
2161 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2164 /* adjust the stack for parameters if
2169 if (ic->parmBytes > 3)
2171 emitcode ("mov", "a,%s", spname);
2172 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2173 emitcode ("mov", "%s,a", spname);
2176 for (i = 0; i < ic->parmBytes; i++)
2177 emitcode ("dec", "%s", spname);
2181 // /* if register bank was saved then unsave them */
2183 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2185 /* if we hade saved some registers then
2187 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2188 unsaveRegisters (ic);
2191 /*-----------------------------------------------------------------*/
2192 /* resultRemat - result is rematerializable */
2193 /*-----------------------------------------------------------------*/
2195 resultRemat (iCode * ic)
2197 if (SKIP_IC (ic) || ic->op == IFX)
2200 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2202 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2203 if (sym->remat && !POINTER_SET (ic))
2210 #if defined(__BORLANDC__) || defined(_MSC_VER)
2211 #define STRCASECMP stricmp
2213 #define STRCASECMP strcasecmp
2216 /*-----------------------------------------------------------------*/
2217 /* inExcludeList - return 1 if the string is in exclude Reg list */
2218 /*-----------------------------------------------------------------*/
2220 inExcludeList (char *s)
2224 if (options.excludeRegs[i] &&
2225 STRCASECMP (options.excludeRegs[i], "none") == 0)
2228 for (i = 0; options.excludeRegs[i]; i++)
2230 if (options.excludeRegs[i] &&
2231 STRCASECMP (s, options.excludeRegs[i]) == 0)
2237 /*-----------------------------------------------------------------*/
2238 /* genFunction - generated code for function entry */
2239 /*-----------------------------------------------------------------*/
2241 genFunction (iCode * ic)
2245 bool switchedPSW = FALSE;
2246 int calleesaves_saved_register = -1;
2249 /* create the function header */
2250 emitcode (";", "-----------------------------------------");
2251 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2252 emitcode (";", "-----------------------------------------");
2254 emitcode ("", "%s:", sym->rname);
2255 ftype = operandType (IC_LEFT (ic));
2257 if (IFFUNC_ISNAKED(ftype))
2259 emitcode(";", "naked function: no prologue.");
2263 /* if critical function then turn interrupts off */
2264 if (IFFUNC_ISCRITICAL (ftype))
2265 emitcode ("clr", "ea");
2267 /* here we need to generate the equates for the
2268 register bank if required */
2269 if (FUNC_REGBANK (ftype) != rbank)
2273 rbank = FUNC_REGBANK (ftype);
2274 for (i = 0; i < mcs51_nRegs; i++)
2276 if (strcmp (regs8051[i].base, "0") == 0)
2277 emitcode ("", "%s = 0x%02x",
2279 8 * rbank + regs8051[i].offset);
2281 emitcode ("", "%s = %s + 0x%02x",
2284 8 * rbank + regs8051[i].offset);
2288 /* if this is an interrupt service routine then
2289 save acc, b, dpl, dph */
2290 if (IFFUNC_ISISR (sym->type))
2293 if (!inExcludeList ("acc"))
2294 emitcode ("push", "acc");
2295 if (!inExcludeList ("b"))
2296 emitcode ("push", "b");
2297 if (!inExcludeList ("dpl"))
2298 emitcode ("push", "dpl");
2299 if (!inExcludeList ("dph"))
2300 emitcode ("push", "dph");
2301 /* if this isr has no bank i.e. is going to
2302 run with bank 0 , then we need to save more
2304 if (!FUNC_REGBANK (sym->type))
2307 /* if this function does not call any other
2308 function then we can be economical and
2309 save only those registers that are used */
2310 if (!IFFUNC_HASFCALL(sym->type))
2314 /* if any registers used */
2317 /* save the registers used */
2318 for (i = 0; i < sym->regsUsed->size; i++)
2320 if (bitVectBitValue (sym->regsUsed, i) ||
2321 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2322 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2330 /* this function has a function call cannot
2331 determines register usage so we will have to push the
2333 saveRBank (0, ic, FALSE);
2334 if (options.parms_in_bank1) {
2336 for (i=0; i < 8 ; i++ ) {
2337 emitcode ("push","%s",rb1regs[i]);
2344 /* This ISR uses a non-zero bank.
2346 * We assume that the bank is available for our
2349 * However, if this ISR calls a function which uses some
2350 * other bank, we must save that bank entirely.
2352 unsigned long banksToSave = 0;
2354 if (IFFUNC_HASFCALL(sym->type))
2357 #define MAX_REGISTER_BANKS 4
2362 for (i = ic; i; i = i->next)
2364 if (i->op == ENDFUNCTION)
2366 /* we got to the end OK. */
2374 dtype = operandType (IC_LEFT(i));
2376 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2378 /* Mark this bank for saving. */
2379 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2381 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2385 banksToSave |= (1 << FUNC_REGBANK(dtype));
2388 /* And note that we don't need to do it in
2396 /* This is a mess; we have no idea what
2397 * register bank the called function might
2400 * The only thing I can think of to do is
2401 * throw a warning and hope.
2403 werror(W_FUNCPTR_IN_USING_ISR);
2407 if (banksToSave && options.useXstack)
2409 /* Since we aren't passing it an ic,
2410 * saveRBank will assume r0 is available to abuse.
2412 * So switch to our (trashable) bank now, so
2413 * the caller's R0 isn't trashed.
2415 emitcode ("push", "psw");
2416 emitcode ("mov", "psw,#0x%02x",
2417 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2421 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2423 if (banksToSave & (1 << ix))
2425 saveRBank(ix, NULL, FALSE);
2429 // jwk: this needs a closer look
2430 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2435 /* if callee-save to be used for this function
2436 then save the registers being used in this function */
2437 if (IFFUNC_CALLEESAVES(sym->type))
2441 /* if any registers used */
2444 /* save the registers used */
2445 for (i = 0; i < sym->regsUsed->size; i++)
2447 if (bitVectBitValue (sym->regsUsed, i) ||
2448 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2450 /* remember one saved register for later usage */
2451 if (calleesaves_saved_register < 0)
2452 calleesaves_saved_register = i;
2453 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2461 /* set the register bank to the desired value */
2462 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2465 emitcode ("push", "psw");
2466 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2469 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2472 if (options.useXstack)
2474 emitcode ("mov", "r0,%s", spname);
2475 emitcode ("mov", "a,_bp");
2476 emitcode ("movx", "@r0,a");
2477 emitcode ("inc", "%s", spname);
2481 /* set up the stack */
2482 emitcode ("push", "_bp"); /* save the callers stack */
2484 emitcode ("mov", "_bp,%s", spname);
2487 /* adjust the stack for the function */
2493 werror (W_STACK_OVERFLOW, sym->name);
2495 if (i > 3 && sym->recvSize < 4)
2498 emitcode ("mov", "a,sp");
2499 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2500 emitcode ("mov", "sp,a");
2505 if (IFFUNC_CALLEESAVES(sym->type))
2507 /* if it's a callee-saves function we need a saved register */
2508 if (calleesaves_saved_register >= 0)
2510 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2511 emitcode ("mov", "a,sp");
2512 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2513 emitcode ("mov", "sp,a");
2514 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2517 /* do it the hard way */
2519 emitcode ("inc", "sp");
2523 /* not callee-saves, we can clobber ar0 */
2524 emitcode ("mov", "ar0,a");
2525 emitcode ("mov", "a,sp");
2526 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2527 emitcode ("mov", "sp,a");
2528 emitcode ("mov", "a,ar0");
2533 emitcode ("inc", "sp");
2539 emitcode ("mov", "a,_spx");
2540 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2541 emitcode ("mov", "_spx,a");
2546 /*-----------------------------------------------------------------*/
2547 /* genEndFunction - generates epilogue for functions */
2548 /*-----------------------------------------------------------------*/
2550 genEndFunction (iCode * ic)
2552 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2554 if (IFFUNC_ISNAKED(sym->type))
2556 emitcode(";", "naked function: no epilogue.");
2560 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2562 emitcode ("mov", "%s,_bp", spname);
2565 /* if use external stack but some variables were
2566 added to the local stack then decrement the
2568 if (options.useXstack && sym->stack)
2570 emitcode ("mov", "a,sp");
2571 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2572 emitcode ("mov", "sp,a");
2576 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2578 if (options.useXstack)
2580 emitcode ("mov", "r0,%s", spname);
2581 emitcode ("movx", "a,@r0");
2582 emitcode ("mov", "_bp,a");
2583 emitcode ("dec", "%s", spname);
2587 emitcode ("pop", "_bp");
2591 /* restore the register bank */
2592 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2594 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2595 || !options.useXstack)
2597 /* Special case of ISR using non-zero bank with useXstack
2600 emitcode ("pop", "psw");
2604 if (IFFUNC_ISISR (sym->type))
2607 /* now we need to restore the registers */
2608 /* if this isr has no bank i.e. is going to
2609 run with bank 0 , then we need to save more
2611 if (!FUNC_REGBANK (sym->type))
2613 /* if this function does not call any other
2614 function then we can be economical and
2615 save only those registers that are used */
2616 if (!IFFUNC_HASFCALL(sym->type))
2620 /* if any registers used */
2623 /* save the registers used */
2624 for (i = sym->regsUsed->size; i >= 0; i--)
2626 if (bitVectBitValue (sym->regsUsed, i) ||
2627 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2635 if (options.parms_in_bank1) {
2637 for (i = 7 ; i >= 0 ; i-- ) {
2638 emitcode ("pop","%s",rb1regs[i]);
2641 /* this function has a function call cannot
2642 determines register usage so we will have to pop the
2644 unsaveRBank (0, ic, FALSE);
2649 /* This ISR uses a non-zero bank.
2651 * Restore any register banks saved by genFunction
2654 // jwk: this needs a closer look
2655 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2658 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2660 if (savedBanks & (1 << ix))
2662 unsaveRBank(ix, NULL, FALSE);
2666 if (options.useXstack)
2668 /* Restore bank AFTER calling unsaveRBank,
2669 * since it can trash r0.
2671 emitcode ("pop", "psw");
2675 if (!inExcludeList ("dph"))
2676 emitcode ("pop", "dph");
2677 if (!inExcludeList ("dpl"))
2678 emitcode ("pop", "dpl");
2679 if (!inExcludeList ("b"))
2680 emitcode ("pop", "b");
2681 if (!inExcludeList ("acc"))
2682 emitcode ("pop", "acc");
2684 if (IFFUNC_ISCRITICAL (sym->type))
2685 emitcode ("setb", "ea");
2687 /* if debug then send end of function */
2688 if (options.debug && currFunc)
2691 emitcode ("", "C$%s$%d$%d$%d ==.",
2692 FileBaseName (ic->filename), currFunc->lastLine,
2693 ic->level, ic->block);
2694 if (IS_STATIC (currFunc->etype))
2695 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2697 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2701 emitcode ("reti", "");
2705 if (IFFUNC_ISCRITICAL (sym->type))
2706 emitcode ("setb", "ea");
2708 if (IFFUNC_CALLEESAVES(sym->type))
2712 /* if any registers used */
2715 /* save the registers used */
2716 for (i = sym->regsUsed->size; i >= 0; i--)
2718 if (bitVectBitValue (sym->regsUsed, i) ||
2719 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2720 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2726 /* if debug then send end of function */
2727 if (options.debug && currFunc)
2730 emitcode ("", "C$%s$%d$%d$%d ==.",
2731 FileBaseName (ic->filename), currFunc->lastLine,
2732 ic->level, ic->block);
2733 if (IS_STATIC (currFunc->etype))
2734 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2736 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2740 emitcode ("ret", "");
2745 /*-----------------------------------------------------------------*/
2746 /* genRet - generate code for return statement */
2747 /*-----------------------------------------------------------------*/
2751 int size, offset = 0, pushed = 0;
2753 D(emitcode (";", "genRet"));
2755 /* if we have no return value then
2756 just generate the "ret" */
2760 /* we have something to return then
2761 move the return value into place */
2762 aopOp (IC_LEFT (ic), ic, FALSE);
2763 size = AOP_SIZE (IC_LEFT (ic));
2768 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2771 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2773 emitcode ("push", "%s", l);
2778 l = aopGet (AOP (IC_LEFT (ic)), offset,
2780 if (strcmp (fReturn[offset], l))
2781 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2790 if (strcmp (fReturn[pushed], "a"))
2791 emitcode ("pop", fReturn[pushed]);
2793 emitcode ("pop", "acc");
2796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2799 /* generate a jump to the return label
2800 if the next is not the return statement */
2801 if (!(ic->next && ic->next->op == LABEL &&
2802 IC_LABEL (ic->next) == returnLabel))
2804 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2808 /*-----------------------------------------------------------------*/
2809 /* genLabel - generates a label */
2810 /*-----------------------------------------------------------------*/
2812 genLabel (iCode * ic)
2814 /* special case never generate */
2815 if (IC_LABEL (ic) == entryLabel)
2818 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2821 /*-----------------------------------------------------------------*/
2822 /* genGoto - generates a ljmp */
2823 /*-----------------------------------------------------------------*/
2825 genGoto (iCode * ic)
2827 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2830 /*-----------------------------------------------------------------*/
2831 /* findLabelBackwards: walks back through the iCode chain looking */
2832 /* for the given label. Returns number of iCode instructions */
2833 /* between that label and given ic. */
2834 /* Returns zero if label not found. */
2835 /*-----------------------------------------------------------------*/
2837 findLabelBackwards (iCode * ic, int key)
2846 /* If we have any pushes or pops, we cannot predict the distance.
2847 I don't like this at all, this should be dealt with in the
2849 if (ic->op == IPUSH || ic->op == IPOP) {
2853 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2862 /*-----------------------------------------------------------------*/
2863 /* genPlusIncr :- does addition with increment if possible */
2864 /*-----------------------------------------------------------------*/
2866 genPlusIncr (iCode * ic)
2868 unsigned int icount;
2869 unsigned int size = getDataSize (IC_RESULT (ic));
2871 /* will try to generate an increment */
2872 /* if the right side is not a literal
2874 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2877 /* if the literal value of the right hand side
2878 is greater than 4 then it is not worth it */
2879 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2882 D(emitcode (";", "genPlusIncr"));
2884 /* if increment 16 bits in register */
2885 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2886 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2894 /* If the next instruction is a goto and the goto target
2895 * is < 10 instructions previous to this, we can generate
2896 * jumps straight to that target.
2898 if (ic->next && ic->next->op == GOTO
2899 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2900 && labelRange <= 10)
2902 emitcode (";", "tail increment optimized");
2903 tlbl = IC_LABEL (ic->next);
2908 tlbl = newiTempLabel (NULL);
2911 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2912 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2913 IS_AOP_PREG (IC_RESULT (ic)))
2914 emitcode ("cjne", "%s,#0x00,%05d$",
2915 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2919 emitcode ("clr", "a");
2920 emitcode ("cjne", "a,%s,%05d$",
2921 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2925 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2928 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2929 IS_AOP_PREG (IC_RESULT (ic)))
2930 emitcode ("cjne", "%s,#0x00,%05d$",
2931 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2934 emitcode ("cjne", "a,%s,%05d$",
2935 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2938 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2943 IS_AOP_PREG (IC_RESULT (ic)))
2944 emitcode ("cjne", "%s,#0x00,%05d$",
2945 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2949 emitcode ("cjne", "a,%s,%05d$",
2950 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2953 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2958 emitcode ("", "%05d$:", tlbl->key + 100);
2963 /* if the sizes are greater than 1 then we cannot */
2964 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2965 AOP_SIZE (IC_LEFT (ic)) > 1)
2968 /* we can if the aops of the left & result match or
2969 if they are in registers and the registers are the
2971 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2976 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2977 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2978 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2984 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2993 /*-----------------------------------------------------------------*/
2994 /* outBitAcc - output a bit in acc */
2995 /*-----------------------------------------------------------------*/
2997 outBitAcc (operand * result)
2999 symbol *tlbl = newiTempLabel (NULL);
3000 /* if the result is a bit */
3001 if (AOP_TYPE (result) == AOP_CRY)
3003 aopPut (AOP (result), "a", 0);
3007 emitcode ("jz", "%05d$", tlbl->key + 100);
3008 emitcode ("mov", "a,%s", one);
3009 emitcode ("", "%05d$:", tlbl->key + 100);
3014 /*-----------------------------------------------------------------*/
3015 /* genPlusBits - generates code for addition of two bits */
3016 /*-----------------------------------------------------------------*/
3018 genPlusBits (iCode * ic)
3020 D(emitcode (";", "genPlusBits"));
3022 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3024 symbol *lbl = newiTempLabel (NULL);
3025 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3026 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3027 emitcode ("cpl", "c");
3028 emitcode ("", "%05d$:", (lbl->key + 100));
3029 outBitC (IC_RESULT (ic));
3033 emitcode ("clr", "a");
3034 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3035 emitcode ("rlc", "a");
3036 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3037 emitcode ("addc", "a,#0x00");
3038 outAcc (IC_RESULT (ic));
3043 /* This is the original version of this code.
3045 * This is being kept around for reference,
3046 * because I am not entirely sure I got it right...
3049 adjustArithmeticResult (iCode * ic)
3051 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3052 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3053 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3054 aopPut (AOP (IC_RESULT (ic)),
3055 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3058 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3059 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3060 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3061 aopPut (AOP (IC_RESULT (ic)),
3062 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3065 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3066 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3067 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3068 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3069 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3072 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3073 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3077 /* This is the pure and virtuous version of this code.
3078 * I'm pretty certain it's right, but not enough to toss the old
3082 adjustArithmeticResult (iCode * ic)
3084 if (opIsGptr (IC_RESULT (ic)) &&
3085 opIsGptr (IC_LEFT (ic)) &&
3086 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3088 aopPut (AOP (IC_RESULT (ic)),
3089 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3093 if (opIsGptr (IC_RESULT (ic)) &&
3094 opIsGptr (IC_RIGHT (ic)) &&
3095 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3097 aopPut (AOP (IC_RESULT (ic)),
3098 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3102 if (opIsGptr (IC_RESULT (ic)) &&
3103 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3104 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3105 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3106 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3109 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3110 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3115 /*-----------------------------------------------------------------*/
3116 /* genPlus - generates code for addition */
3117 /*-----------------------------------------------------------------*/
3119 genPlus (iCode * ic)
3121 int size, offset = 0;
3123 asmop *leftOp, *rightOp;
3125 /* special cases :- */
3127 D(emitcode (";", "genPlus"));
3129 aopOp (IC_LEFT (ic), ic, FALSE);
3130 aopOp (IC_RIGHT (ic), ic, FALSE);
3131 aopOp (IC_RESULT (ic), ic, TRUE);
3133 /* if literal, literal on the right or
3134 if left requires ACC or right is already
3136 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3137 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3138 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3140 operand *t = IC_RIGHT (ic);
3141 IC_RIGHT (ic) = IC_LEFT (ic);
3145 /* if both left & right are in bit
3147 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3148 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3154 /* if left in bit space & right literal */
3155 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3156 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3158 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3159 /* if result in bit space */
3160 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3162 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3163 emitcode ("cpl", "c");
3164 outBitC (IC_RESULT (ic));
3168 size = getDataSize (IC_RESULT (ic));
3171 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3172 emitcode ("addc", "a,#00");
3173 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3179 /* if I can do an increment instead
3180 of add then GOOD for ME */
3181 if (genPlusIncr (ic) == TRUE)
3184 size = getDataSize (IC_RESULT (ic));
3186 leftOp = AOP(IC_LEFT(ic));
3187 rightOp = AOP(IC_RIGHT(ic));
3192 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3194 emitcode("mov", "b,acc");
3195 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3196 emitcode("xch", "a,b");
3197 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3198 emitcode (add, "a,b");
3200 else if (aopGetUsesAcc (leftOp, offset))
3202 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3203 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3207 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3208 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3210 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3211 add = "addc"; /* further adds must propagate carry */
3214 adjustArithmeticResult (ic);
3217 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3218 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3219 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3222 /*-----------------------------------------------------------------*/
3223 /* genMinusDec :- does subtraction with deccrement if possible */
3224 /*-----------------------------------------------------------------*/
3226 genMinusDec (iCode * ic)
3228 unsigned int icount;
3229 unsigned int size = getDataSize (IC_RESULT (ic));
3231 /* will try to generate an increment */
3232 /* if the right side is not a literal
3234 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3237 /* if the literal value of the right hand side
3238 is greater than 4 then it is not worth it */
3239 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3242 D(emitcode (";", "genMinusDec"));
3244 /* if decrement 16 bits in register */
3245 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3246 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3254 /* If the next instruction is a goto and the goto target
3255 * is <= 10 instructions previous to this, we can generate
3256 * jumps straight to that target.
3258 if (ic->next && ic->next->op == GOTO
3259 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3260 && labelRange <= 10)
3262 emitcode (";", "tail decrement optimized");
3263 tlbl = IC_LABEL (ic->next);
3268 tlbl = newiTempLabel (NULL);
3272 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3273 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3274 IS_AOP_PREG (IC_RESULT (ic)))
3275 emitcode ("cjne", "%s,#0xff,%05d$"
3276 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3280 emitcode ("mov", "a,#0xff");
3281 emitcode ("cjne", "a,%s,%05d$"
3282 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3285 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3288 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3289 IS_AOP_PREG (IC_RESULT (ic)))
3290 emitcode ("cjne", "%s,#0xff,%05d$"
3291 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3295 emitcode ("cjne", "a,%s,%05d$"
3296 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3299 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3303 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3304 IS_AOP_PREG (IC_RESULT (ic)))
3305 emitcode ("cjne", "%s,#0xff,%05d$"
3306 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3310 emitcode ("cjne", "a,%s,%05d$"
3311 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3314 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3318 emitcode ("", "%05d$:", tlbl->key + 100);
3323 /* if the sizes are greater than 1 then we cannot */
3324 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3325 AOP_SIZE (IC_LEFT (ic)) > 1)
3328 /* we can if the aops of the left & result match or
3329 if they are in registers and the registers are the
3331 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3335 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3343 /*-----------------------------------------------------------------*/
3344 /* addSign - complete with sign */
3345 /*-----------------------------------------------------------------*/
3347 addSign (operand * result, int offset, int sign)
3349 int size = (getDataSize (result) - offset);
3354 emitcode ("rlc", "a");
3355 emitcode ("subb", "a,acc");
3357 aopPut (AOP (result), "a", offset++);
3361 aopPut (AOP (result), zero, offset++);
3365 /*-----------------------------------------------------------------*/
3366 /* genMinusBits - generates code for subtraction of two bits */
3367 /*-----------------------------------------------------------------*/
3369 genMinusBits (iCode * ic)
3371 symbol *lbl = newiTempLabel (NULL);
3373 D(emitcode (";", "genMinusBits"));
3375 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3377 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3378 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3379 emitcode ("cpl", "c");
3380 emitcode ("", "%05d$:", (lbl->key + 100));
3381 outBitC (IC_RESULT (ic));
3385 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3386 emitcode ("subb", "a,acc");
3387 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3388 emitcode ("inc", "a");
3389 emitcode ("", "%05d$:", (lbl->key + 100));
3390 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3391 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3395 /*-----------------------------------------------------------------*/
3396 /* genMinus - generates code for subtraction */
3397 /*-----------------------------------------------------------------*/
3399 genMinus (iCode * ic)
3401 int size, offset = 0;
3403 D(emitcode (";", "genMinus"));
3405 aopOp (IC_LEFT (ic), ic, FALSE);
3406 aopOp (IC_RIGHT (ic), ic, FALSE);
3407 aopOp (IC_RESULT (ic), ic, TRUE);
3409 /* special cases :- */
3410 /* if both left & right are in bit space */
3411 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3412 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3418 /* if I can do an decrement instead
3419 of subtract then GOOD for ME */
3420 if (genMinusDec (ic) == TRUE)
3423 size = getDataSize (IC_RESULT (ic));
3425 /* if literal, add a,#-lit, else normal subb */
3426 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3428 unsigned long lit = 0L;
3430 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3435 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3436 /* first add without previous c */
3438 if (!size && lit==-1) {
3439 emitcode ("dec", "a");
3441 emitcode ("add", "a,#0x%02x",
3442 (unsigned int) (lit & 0x0FFL));
3445 emitcode ("addc", "a,#0x%02x",
3446 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3448 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3453 asmop *leftOp, *rightOp;
3455 leftOp = AOP(IC_LEFT(ic));
3456 rightOp = AOP(IC_RIGHT(ic));
3460 if (aopGetUsesAcc(rightOp, offset)) {
3461 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3462 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3464 emitcode( "cpl", "c");
3466 emitcode( "setb", "c");
3468 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3469 emitcode("cpl", "a");
3471 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3474 emitcode ("subb", "a,%s",
3475 aopGet(rightOp, offset, FALSE, TRUE));
3478 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3483 adjustArithmeticResult (ic);
3486 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3487 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3492 /*-----------------------------------------------------------------*/
3493 /* genMultbits :- multiplication of bits */
3494 /*-----------------------------------------------------------------*/
3496 genMultbits (operand * left,
3500 D(emitcode (";", "genMultbits"));
3502 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3503 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3508 /*-----------------------------------------------------------------*/
3509 /* genMultOneByte : 8*8=8/16 bit multiplication */
3510 /*-----------------------------------------------------------------*/
3512 genMultOneByte (operand * left,
3516 sym_link *opetype = operandType (result);
3518 int size=AOP_SIZE(result);
3520 D(emitcode (";", "genMultOneByte"));
3522 if (size<1 || size>2) {
3523 // this should never happen
3524 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3525 AOP_SIZE(result), __FILE__, lineno);
3529 /* (if two literals: the value is computed before) */
3530 /* if one literal, literal on the right */
3531 if (AOP_TYPE (left) == AOP_LIT)
3536 //emitcode (";", "swapped left and right");
3539 if (SPEC_USIGN(opetype)
3540 // ignore the sign of left and right, what else can we do?
3541 || (SPEC_USIGN(operandType(left)) &&
3542 SPEC_USIGN(operandType(right)))) {
3543 // just an unsigned 8*8=8/16 multiply
3544 //emitcode (";","unsigned");
3545 // TODO: check for accumulator clash between left & right aops?
3546 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3547 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3548 emitcode ("mul", "ab");
3549 aopPut (AOP (result), "a", 0);
3551 aopPut (AOP (result), "b", 1);
3556 // we have to do a signed multiply
3558 //emitcode (";", "signed");
3559 emitcode ("clr", "F0"); // reset sign flag
3560 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3562 lbl=newiTempLabel(NULL);
3563 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3564 // left side is negative, 8-bit two's complement, this fails for -128
3565 emitcode ("setb", "F0"); // set sign flag
3566 emitcode ("cpl", "a");
3567 emitcode ("inc", "a");
3569 emitcode ("", "%05d$:", lbl->key+100);
3572 if (AOP_TYPE(right)==AOP_LIT) {
3573 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3574 /* AND literal negative */
3576 emitcode ("cpl", "F0"); // complement sign flag
3577 emitcode ("mov", "b,#0x%02x", -val);
3579 emitcode ("mov", "b,#0x%02x", val);
3582 lbl=newiTempLabel(NULL);
3583 emitcode ("mov", "b,a");
3584 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3585 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3586 // right side is negative, 8-bit two's complement
3587 emitcode ("cpl", "F0"); // complement sign flag
3588 emitcode ("cpl", "a");
3589 emitcode ("inc", "a");
3590 emitcode ("", "%05d$:", lbl->key+100);
3592 emitcode ("mul", "ab");
3594 lbl=newiTempLabel(NULL);
3595 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3596 // only ONE op was negative, we have to do a 8/16-bit two's complement
3597 emitcode ("cpl", "a"); // lsb
3599 emitcode ("inc", "a");
3601 emitcode ("add", "a,#1");
3602 emitcode ("xch", "a,b");
3603 emitcode ("cpl", "a"); // msb
3604 emitcode ("addc", "a,#0");
3605 emitcode ("xch", "a,b");
3608 emitcode ("", "%05d$:", lbl->key+100);
3609 aopPut (AOP (result), "a", 0);
3611 aopPut (AOP (result), "b", 1);
3615 /*-----------------------------------------------------------------*/
3616 /* genMult - generates code for multiplication */
3617 /*-----------------------------------------------------------------*/
3619 genMult (iCode * ic)
3621 operand *left = IC_LEFT (ic);
3622 operand *right = IC_RIGHT (ic);
3623 operand *result = IC_RESULT (ic);
3625 D(emitcode (";", "genMult"));
3627 /* assign the amsops */
3628 aopOp (left, ic, FALSE);
3629 aopOp (right, ic, FALSE);
3630 aopOp (result, ic, TRUE);
3632 /* special cases first */
3634 if (AOP_TYPE (left) == AOP_CRY &&
3635 AOP_TYPE (right) == AOP_CRY)
3637 genMultbits (left, right, result);
3641 /* if both are of size == 1 */
3642 #if 0 // one of them can be a sloc shared with the result
3643 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3645 if (getSize(operandType(left)) == 1 &&
3646 getSize(operandType(right)) == 1)
3649 genMultOneByte (left, right, result);
3653 /* should have been converted to function call */
3654 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3655 getSize(OP_SYMBOL(right)->type));
3659 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3660 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3661 freeAsmop (result, NULL, ic, TRUE);
3664 /*-----------------------------------------------------------------*/
3665 /* genDivbits :- division of bits */
3666 /*-----------------------------------------------------------------*/
3668 genDivbits (operand * left,
3675 D(emitcode (";", "genDivbits"));
3677 /* the result must be bit */
3678 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3679 l = aopGet (AOP (left), 0, FALSE, FALSE);
3683 emitcode ("div", "ab");
3684 emitcode ("rrc", "a");
3685 aopPut (AOP (result), "c", 0);
3688 /*-----------------------------------------------------------------*/
3689 /* genDivOneByte : 8 bit division */
3690 /*-----------------------------------------------------------------*/
3692 genDivOneByte (operand * left,
3696 sym_link *opetype = operandType (result);
3701 D(emitcode (";", "genDivOneByte"));
3703 size = AOP_SIZE (result) - 1;
3705 /* signed or unsigned */
3706 if (SPEC_USIGN (opetype))
3708 /* unsigned is easy */
3709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3710 l = aopGet (AOP (left), 0, FALSE, FALSE);
3712 emitcode ("div", "ab");
3713 aopPut (AOP (result), "a", 0);
3715 aopPut (AOP (result), zero, offset++);
3719 /* signed is a little bit more difficult */
3721 /* save the signs of the operands */
3722 l = aopGet (AOP (left), 0, FALSE, FALSE);
3724 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3725 emitcode ("push", "acc"); /* save it on the stack */
3727 /* now sign adjust for both left & right */
3728 l = aopGet (AOP (right), 0, FALSE, FALSE);
3730 lbl = newiTempLabel (NULL);
3731 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3732 emitcode ("cpl", "a");
3733 emitcode ("inc", "a");
3734 emitcode ("", "%05d$:", (lbl->key + 100));
3735 emitcode ("mov", "b,a");
3737 /* sign adjust left side */
3738 l = aopGet (AOP (left), 0, FALSE, FALSE);
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3745 emitcode ("", "%05d$:", (lbl->key + 100));
3747 /* now the division */
3748 emitcode ("div", "ab");
3749 /* we are interested in the lower order
3751 emitcode ("mov", "b,a");
3752 lbl = newiTempLabel (NULL);
3753 emitcode ("pop", "acc");
3754 /* if there was an over flow we don't
3755 adjust the sign of the result */
3756 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3757 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3759 emitcode ("clr", "a");
3760 emitcode ("subb", "a,b");
3761 emitcode ("mov", "b,a");
3762 emitcode ("", "%05d$:", (lbl->key + 100));
3764 /* now we are done */
3765 aopPut (AOP (result), "b", 0);
3768 emitcode ("mov", "c,b.7");
3769 emitcode ("subb", "a,acc");
3772 aopPut (AOP (result), "a", offset++);
3776 /*-----------------------------------------------------------------*/
3777 /* genDiv - generates code for division */
3778 /*-----------------------------------------------------------------*/
3782 operand *left = IC_LEFT (ic);
3783 operand *right = IC_RIGHT (ic);
3784 operand *result = IC_RESULT (ic);
3786 D(emitcode (";", "genDiv"));
3788 /* assign the amsops */
3789 aopOp (left, ic, FALSE);
3790 aopOp (right, ic, FALSE);
3791 aopOp (result, ic, TRUE);
3793 /* special cases first */
3795 if (AOP_TYPE (left) == AOP_CRY &&
3796 AOP_TYPE (right) == AOP_CRY)
3798 genDivbits (left, right, result);
3802 /* if both are of size == 1 */
3803 if (AOP_SIZE (left) == 1 &&
3804 AOP_SIZE (right) == 1)
3806 genDivOneByte (left, right, result);
3810 /* should have been converted to function call */
3813 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (result, NULL, ic, TRUE);
3818 /*-----------------------------------------------------------------*/
3819 /* genModbits :- modulus of bits */
3820 /*-----------------------------------------------------------------*/
3822 genModbits (operand * left,
3829 D(emitcode (";", "genModbits"));
3831 /* the result must be bit */
3832 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3833 l = aopGet (AOP (left), 0, FALSE, FALSE);
3837 emitcode ("div", "ab");
3838 emitcode ("mov", "a,b");
3839 emitcode ("rrc", "a");
3840 aopPut (AOP (result), "c", 0);
3843 /*-----------------------------------------------------------------*/
3844 /* genModOneByte : 8 bit modulus */
3845 /*-----------------------------------------------------------------*/
3847 genModOneByte (operand * left,
3851 sym_link *opetype = operandType (result);
3855 D(emitcode (";", "genModOneByte"));
3857 /* signed or unsigned */
3858 if (SPEC_USIGN (opetype))
3860 /* unsigned is easy */
3861 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3862 l = aopGet (AOP (left), 0, FALSE, FALSE);
3864 emitcode ("div", "ab");
3865 aopPut (AOP (result), "b", 0);
3869 /* signed is a little bit more difficult */
3871 /* save the signs of the operands */
3872 l = aopGet (AOP (left), 0, FALSE, FALSE);
3875 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3876 emitcode ("push", "acc"); /* save it on the stack */
3878 /* now sign adjust for both left & right */
3879 l = aopGet (AOP (right), 0, FALSE, FALSE);
3882 lbl = newiTempLabel (NULL);
3883 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884 emitcode ("cpl", "a");
3885 emitcode ("inc", "a");
3886 emitcode ("", "%05d$:", (lbl->key + 100));
3887 emitcode ("mov", "b,a");
3889 /* sign adjust left side */
3890 l = aopGet (AOP (left), 0, FALSE, FALSE);
3893 lbl = newiTempLabel (NULL);
3894 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("cpl", "a");
3896 emitcode ("inc", "a");
3897 emitcode ("", "%05d$:", (lbl->key + 100));
3899 /* now the multiplication */
3900 emitcode ("div", "ab");
3901 /* we are interested in the lower order
3903 lbl = newiTempLabel (NULL);
3904 emitcode ("pop", "acc");
3905 /* if there was an over flow we don't
3906 adjust the sign of the result */
3907 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3908 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3910 emitcode ("clr", "a");
3911 emitcode ("subb", "a,b");
3912 emitcode ("mov", "b,a");
3913 emitcode ("", "%05d$:", (lbl->key + 100));
3915 /* now we are done */
3916 aopPut (AOP (result), "b", 0);
3920 /*-----------------------------------------------------------------*/
3921 /* genMod - generates code for division */
3922 /*-----------------------------------------------------------------*/
3926 operand *left = IC_LEFT (ic);
3927 operand *right = IC_RIGHT (ic);
3928 operand *result = IC_RESULT (ic);
3930 D(emitcode (";", "genMod"));
3932 /* assign the amsops */
3933 aopOp (left, ic, FALSE);
3934 aopOp (right, ic, FALSE);
3935 aopOp (result, ic, TRUE);
3937 /* special cases first */
3939 if (AOP_TYPE (left) == AOP_CRY &&
3940 AOP_TYPE (right) == AOP_CRY)
3942 genModbits (left, right, result);
3946 /* if both are of size == 1 */
3947 if (AOP_SIZE (left) == 1 &&
3948 AOP_SIZE (right) == 1)
3950 genModOneByte (left, right, result);
3954 /* should have been converted to function call */
3958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3960 freeAsmop (result, NULL, ic, TRUE);
3963 /*-----------------------------------------------------------------*/
3964 /* genIfxJump :- will create a jump depending on the ifx */
3965 /*-----------------------------------------------------------------*/
3967 genIfxJump (iCode * ic, char *jval)
3970 symbol *tlbl = newiTempLabel (NULL);
3973 D(emitcode (";", "genIfxJump"));
3975 /* if true label then we jump if condition
3979 jlbl = IC_TRUE (ic);
3980 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3981 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3985 /* false label is present */
3986 jlbl = IC_FALSE (ic);
3987 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3988 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3990 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3991 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3993 emitcode (inst, "%05d$", tlbl->key + 100);
3994 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3995 emitcode ("", "%05d$:", tlbl->key + 100);
3997 /* mark the icode as generated */
4001 /*-----------------------------------------------------------------*/
4002 /* genCmp :- greater or less than comparison */
4003 /*-----------------------------------------------------------------*/
4005 genCmp (operand * left, operand * right,
4006 operand * result, iCode * ifx, int sign, iCode *ic)
4008 int size, offset = 0;
4009 unsigned long lit = 0L;
4011 D(emitcode (";", "genCmp"));
4013 /* if left & right are bit variables */
4014 if (AOP_TYPE (left) == AOP_CRY &&
4015 AOP_TYPE (right) == AOP_CRY)
4017 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4018 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4022 /* subtract right from left if at the
4023 end the carry flag is set then we know that
4024 left is greater than right */
4025 size = max (AOP_SIZE (left), AOP_SIZE (right));
4027 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4028 if ((size == 1) && !sign &&
4029 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4031 symbol *lbl = newiTempLabel (NULL);
4032 emitcode ("cjne", "%s,%s,%05d$",
4033 aopGet (AOP (left), offset, FALSE, FALSE),
4034 aopGet (AOP (right), offset, FALSE, FALSE),
4036 emitcode ("", "%05d$:", lbl->key + 100);
4040 if (AOP_TYPE (right) == AOP_LIT)
4042 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4043 /* optimize if(x < 0) or if(x >= 0) */
4052 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4053 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4055 genIfxJump (ifx, "acc.7");
4059 emitcode ("rlc", "a");
4067 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4068 if (sign && size == 0)
4070 emitcode ("xrl", "a,#0x80");
4071 if (AOP_TYPE (right) == AOP_LIT)
4073 unsigned long lit = (unsigned long)
4074 floatFromVal (AOP (right)->aopu.aop_lit);
4075 emitcode ("subb", "a,#0x%02x",
4076 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4080 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4081 emitcode ("xrl", "b,#0x80");
4082 emitcode ("subb", "a,b");
4086 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4100 /* if the result is used in the next
4101 ifx conditional branch then generate
4102 code a little differently */
4104 genIfxJump (ifx, "c");
4107 /* leave the result in acc */
4111 /*-----------------------------------------------------------------*/
4112 /* genCmpGt :- greater than comparison */
4113 /*-----------------------------------------------------------------*/
4115 genCmpGt (iCode * ic, iCode * ifx)
4117 operand *left, *right, *result;
4118 sym_link *letype, *retype;
4121 D(emitcode (";", "genCmpGt"));
4123 left = IC_LEFT (ic);
4124 right = IC_RIGHT (ic);
4125 result = IC_RESULT (ic);
4127 letype = getSpec (operandType (left));
4128 retype = getSpec (operandType (right));
4129 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4130 /* assign the amsops */
4131 aopOp (left, ic, FALSE);
4132 aopOp (right, ic, FALSE);
4133 aopOp (result, ic, TRUE);
4135 genCmp (right, left, result, ifx, sign,ic);
4137 freeAsmop (result, NULL, ic, TRUE);
4140 /*-----------------------------------------------------------------*/
4141 /* genCmpLt - less than comparisons */
4142 /*-----------------------------------------------------------------*/
4144 genCmpLt (iCode * ic, iCode * ifx)
4146 operand *left, *right, *result;
4147 sym_link *letype, *retype;
4150 D(emitcode (";", "genCmpLt"));
4152 left = IC_LEFT (ic);
4153 right = IC_RIGHT (ic);
4154 result = IC_RESULT (ic);
4156 letype = getSpec (operandType (left));
4157 retype = getSpec (operandType (right));
4158 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4160 /* assign the amsops */
4161 aopOp (left, ic, FALSE);
4162 aopOp (right, ic, FALSE);
4163 aopOp (result, ic, TRUE);
4165 genCmp (left, right, result, ifx, sign,ic);
4167 freeAsmop (result, NULL, ic, TRUE);
4170 /*-----------------------------------------------------------------*/
4171 /* gencjneshort - compare and jump if not equal */
4172 /*-----------------------------------------------------------------*/
4174 gencjneshort (operand * left, operand * right, symbol * lbl)
4176 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4178 unsigned long lit = 0L;
4180 /* if the left side is a literal or
4181 if the right is in a pointer register and left
4183 if ((AOP_TYPE (left) == AOP_LIT) ||
4184 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4190 if (AOP_TYPE (right) == AOP_LIT)
4191 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4193 /* if the right side is a literal then anything goes */
4194 if (AOP_TYPE (right) == AOP_LIT &&
4195 AOP_TYPE (left) != AOP_DIR)
4199 emitcode ("cjne", "%s,%s,%05d$",
4200 aopGet (AOP (left), offset, FALSE, FALSE),
4201 aopGet (AOP (right), offset, FALSE, FALSE),
4207 /* if the right side is in a register or in direct space or
4208 if the left is a pointer register & right is not */
4209 else if (AOP_TYPE (right) == AOP_REG ||
4210 AOP_TYPE (right) == AOP_DIR ||
4211 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4212 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4216 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4217 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4218 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4219 emitcode ("jnz", "%05d$", lbl->key + 100);
4221 emitcode ("cjne", "a,%s,%05d$",
4222 aopGet (AOP (right), offset, FALSE, TRUE),
4229 /* right is a pointer reg need both a & b */
4232 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4233 if (strcmp (l, "b"))
4234 emitcode ("mov", "b,%s", l);
4235 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4236 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4242 /*-----------------------------------------------------------------*/
4243 /* gencjne - compare and jump if not equal */
4244 /*-----------------------------------------------------------------*/
4246 gencjne (operand * left, operand * right, symbol * lbl)
4248 symbol *tlbl = newiTempLabel (NULL);
4250 gencjneshort (left, right, lbl);
4252 emitcode ("mov", "a,%s", one);
4253 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4254 emitcode ("", "%05d$:", lbl->key + 100);
4255 emitcode ("clr", "a");
4256 emitcode ("", "%05d$:", tlbl->key + 100);
4259 /*-----------------------------------------------------------------*/
4260 /* genCmpEq - generates code for equal to */
4261 /*-----------------------------------------------------------------*/
4263 genCmpEq (iCode * ic, iCode * ifx)
4265 operand *left, *right, *result;
4267 D(emitcode (";", "genCmpEq"));
4269 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4270 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4271 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4273 /* if literal, literal on the right or
4274 if the right is in a pointer register and left
4276 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4277 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4279 operand *t = IC_RIGHT (ic);
4280 IC_RIGHT (ic) = IC_LEFT (ic);
4284 if (ifx && !AOP_SIZE (result))
4287 /* if they are both bit variables */
4288 if (AOP_TYPE (left) == AOP_CRY &&
4289 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4291 if (AOP_TYPE (right) == AOP_LIT)
4293 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4297 emitcode ("cpl", "c");
4301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4305 emitcode ("clr", "c");
4307 /* AOP_TYPE(right) == AOP_CRY */
4311 symbol *lbl = newiTempLabel (NULL);
4312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4313 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4314 emitcode ("cpl", "c");
4315 emitcode ("", "%05d$:", (lbl->key + 100));
4317 /* if true label then we jump if condition
4319 tlbl = newiTempLabel (NULL);
4322 emitcode ("jnc", "%05d$", tlbl->key + 100);
4323 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4327 emitcode ("jc", "%05d$", tlbl->key + 100);
4328 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4330 emitcode ("", "%05d$:", tlbl->key + 100);
4334 tlbl = newiTempLabel (NULL);
4335 gencjneshort (left, right, tlbl);
4338 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4339 emitcode ("", "%05d$:", tlbl->key + 100);
4343 symbol *lbl = newiTempLabel (NULL);
4344 emitcode ("sjmp", "%05d$", lbl->key + 100);
4345 emitcode ("", "%05d$:", tlbl->key + 100);
4346 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4347 emitcode ("", "%05d$:", lbl->key + 100);
4350 /* mark the icode as generated */
4355 /* if they are both bit variables */
4356 if (AOP_TYPE (left) == AOP_CRY &&
4357 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4359 if (AOP_TYPE (right) == AOP_LIT)
4361 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4365 emitcode ("cpl", "c");
4369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4373 emitcode ("clr", "c");
4375 /* AOP_TYPE(right) == AOP_CRY */
4379 symbol *lbl = newiTempLabel (NULL);
4380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4381 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4382 emitcode ("cpl", "c");
4383 emitcode ("", "%05d$:", (lbl->key + 100));
4386 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4393 genIfxJump (ifx, "c");
4396 /* if the result is used in an arithmetic operation
4397 then put the result in place */
4402 gencjne (left, right, newiTempLabel (NULL));
4403 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4405 aopPut (AOP (result), "a", 0);
4410 genIfxJump (ifx, "a");
4413 /* if the result is used in an arithmetic operation
4414 then put the result in place */
4415 if (AOP_TYPE (result) != AOP_CRY)
4417 /* leave the result in acc */
4421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423 freeAsmop (result, NULL, ic, TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* ifxForOp - returns the icode containing the ifx for operand */
4428 /*-----------------------------------------------------------------*/
4430 ifxForOp (operand * op, iCode * ic)
4432 /* if true symbol then needs to be assigned */
4433 if (IS_TRUE_SYMOP (op))
4436 /* if this has register type condition and
4437 the next instruction is ifx with the same operand
4438 and live to of the operand is upto the ifx only then */
4440 ic->next->op == IFX &&
4441 IC_COND (ic->next)->key == op->key &&
4442 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4448 /*-----------------------------------------------------------------*/
4449 /* hasInc - operand is incremented before any other use */
4450 /*-----------------------------------------------------------------*/
4452 hasInc (operand *op, iCode *ic,int osize)
4454 sym_link *type = operandType(op);
4455 sym_link *retype = getSpec (type);
4456 iCode *lic = ic->next;
4459 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4460 if (!IS_SYMOP(op)) return NULL;
4462 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4463 if (IS_AGGREGATE(type->next)) return NULL;
4464 if (osize != (isize = getSize(type->next))) return NULL;
4467 /* if operand of the form op = op + <sizeof *op> */
4468 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4469 isOperandEqual(IC_RESULT(lic),op) &&
4470 isOperandLiteral(IC_RIGHT(lic)) &&
4471 operandLitValue(IC_RIGHT(lic)) == isize) {
4474 /* if the operand used or deffed */
4475 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4478 /* if GOTO or IFX */
4479 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4485 /*-----------------------------------------------------------------*/
4486 /* genAndOp - for && operation */
4487 /*-----------------------------------------------------------------*/
4489 genAndOp (iCode * ic)
4491 operand *left, *right, *result;
4494 D(emitcode (";", "genAndOp"));
4496 /* note here that && operations that are in an
4497 if statement are taken away by backPatchLabels
4498 only those used in arthmetic operations remain */
4499 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4500 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4501 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4503 /* if both are bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 AOP_TYPE (right) == AOP_CRY)
4507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4508 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4513 tlbl = newiTempLabel (NULL);
4515 emitcode ("jz", "%05d$", tlbl->key + 100);
4517 emitcode ("", "%05d$:", tlbl->key + 100);
4521 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4523 freeAsmop (result, NULL, ic, TRUE);
4527 /*-----------------------------------------------------------------*/
4528 /* genOrOp - for || operation */
4529 /*-----------------------------------------------------------------*/
4531 genOrOp (iCode * ic)
4533 operand *left, *right, *result;
4536 D(emitcode (";", "genOrOp"));
4538 /* note here that || operations that are in an
4539 if statement are taken away by backPatchLabels
4540 only those used in arthmetic operations remain */
4541 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4542 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4543 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4545 /* if both are bit variables */
4546 if (AOP_TYPE (left) == AOP_CRY &&
4547 AOP_TYPE (right) == AOP_CRY)
4549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4550 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4555 tlbl = newiTempLabel (NULL);
4557 emitcode ("jnz", "%05d$", tlbl->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (result, NULL, ic, TRUE);
4568 /*-----------------------------------------------------------------*/
4569 /* isLiteralBit - test if lit == 2^n */
4570 /*-----------------------------------------------------------------*/
4572 isLiteralBit (unsigned long lit)
4574 unsigned long pw[32] =
4575 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4576 0x100L, 0x200L, 0x400L, 0x800L,
4577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4584 for (idx = 0; idx < 32; idx++)
4590 /*-----------------------------------------------------------------*/
4591 /* continueIfTrue - */
4592 /*-----------------------------------------------------------------*/
4594 continueIfTrue (iCode * ic)
4597 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4601 /*-----------------------------------------------------------------*/
4603 /*-----------------------------------------------------------------*/
4605 jumpIfTrue (iCode * ic)
4608 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4612 /*-----------------------------------------------------------------*/
4613 /* jmpTrueOrFalse - */
4614 /*-----------------------------------------------------------------*/
4616 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4618 // ugly but optimized by peephole
4621 symbol *nlbl = newiTempLabel (NULL);
4622 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4623 emitcode ("", "%05d$:", tlbl->key + 100);
4624 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4625 emitcode ("", "%05d$:", nlbl->key + 100);
4629 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4630 emitcode ("", "%05d$:", tlbl->key + 100);
4635 /*-----------------------------------------------------------------*/
4636 /* genAnd - code for and */
4637 /*-----------------------------------------------------------------*/
4639 genAnd (iCode * ic, iCode * ifx)
4641 operand *left, *right, *result;
4642 int size, offset = 0;
4643 unsigned long lit = 0L;
4647 D(emitcode (";", "genAnd"));
4649 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4650 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4651 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4654 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4656 AOP_TYPE (left), AOP_TYPE (right));
4657 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4659 AOP_SIZE (left), AOP_SIZE (right));
4662 /* if left is a literal & right is not then exchange them */
4663 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4664 AOP_NEEDSACC (left))
4666 operand *tmp = right;
4671 /* if result = right then exchange them */
4672 if (sameRegs (AOP (result), AOP (right)))
4674 operand *tmp = right;
4679 /* if right is bit then exchange them */
4680 if (AOP_TYPE (right) == AOP_CRY &&
4681 AOP_TYPE (left) != AOP_CRY)
4683 operand *tmp = right;
4687 if (AOP_TYPE (right) == AOP_LIT)
4688 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4690 size = AOP_SIZE (result);
4693 // result = bit & yy;
4694 if (AOP_TYPE (left) == AOP_CRY)
4696 // c = bit & literal;
4697 if (AOP_TYPE (right) == AOP_LIT)
4701 if (size && sameRegs (AOP (result), AOP (left)))
4704 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709 if (size && (AOP_TYPE (result) == AOP_CRY))
4711 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4714 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4719 emitcode ("clr", "c");
4724 if (AOP_TYPE (right) == AOP_CRY)
4727 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4733 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4735 emitcode ("rrc", "a");
4736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4744 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4745 genIfxJump (ifx, "c");
4749 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4750 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4751 if ((AOP_TYPE (right) == AOP_LIT) &&
4752 (AOP_TYPE (result) == AOP_CRY) &&
4753 (AOP_TYPE (left) != AOP_CRY))
4755 int posbit = isLiteralBit (lit);
4760 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4763 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4769 sprintf (buffer, "acc.%d", posbit & 0x07);
4770 genIfxJump (ifx, buffer);
4777 symbol *tlbl = newiTempLabel (NULL);
4778 int sizel = AOP_SIZE (left);
4780 emitcode ("setb", "c");
4783 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4785 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4787 if ((posbit = isLiteralBit (bytelit)) != 0)
4788 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4791 if (bytelit != 0x0FFL)
4792 emitcode ("anl", "a,%s",
4793 aopGet (AOP (right), offset, FALSE, TRUE));
4794 emitcode ("jnz", "%05d$", tlbl->key + 100);
4799 // bit = left & literal
4802 emitcode ("clr", "c");
4803 emitcode ("", "%05d$:", tlbl->key + 100);
4805 // if(left & literal)
4809 jmpTrueOrFalse (ifx, tlbl);
4817 /* if left is same as result */
4818 if (sameRegs (AOP (result), AOP (left)))
4820 for (; size--; offset++)
4822 if (AOP_TYPE (right) == AOP_LIT)
4824 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4826 else if (bytelit == 0)
4827 aopPut (AOP (result), zero, offset);
4828 else if (IS_AOP_PREG (result))
4830 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4831 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4832 aopPut (AOP (result), "a", offset);
4835 emitcode ("anl", "%s,%s",
4836 aopGet (AOP (left), offset, FALSE, TRUE),
4837 aopGet (AOP (right), offset, FALSE, FALSE));
4841 if (AOP_TYPE (left) == AOP_ACC)
4842 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4845 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4846 if (IS_AOP_PREG (result))
4848 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4849 aopPut (AOP (result), "a", offset);
4853 emitcode ("anl", "%s,a",
4854 aopGet (AOP (left), offset, FALSE, TRUE));
4861 // left & result in different registers
4862 if (AOP_TYPE (result) == AOP_CRY)
4865 // if(size), result in bit
4866 // if(!size && ifx), conditional oper: if(left & right)
4867 symbol *tlbl = newiTempLabel (NULL);
4868 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4870 emitcode ("setb", "c");
4873 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4874 emitcode ("anl", "a,%s",
4875 aopGet (AOP (right), offset, FALSE, FALSE));
4877 if (AOP_TYPE(left)==AOP_ACC) {
4878 emitcode("mov", "b,a");
4879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4880 emitcode("anl", "a,b");
4882 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4883 emitcode ("anl", "a,%s",
4884 aopGet (AOP (left), offset, FALSE, FALSE));
4887 emitcode ("jnz", "%05d$", tlbl->key + 100);
4893 emitcode ("", "%05d$:", tlbl->key + 100);
4897 jmpTrueOrFalse (ifx, tlbl);
4901 for (; (size--); offset++)
4904 // result = left & right
4905 if (AOP_TYPE (right) == AOP_LIT)
4907 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4909 aopPut (AOP (result),
4910 aopGet (AOP (left), offset, FALSE, FALSE),
4914 else if (bytelit == 0)
4916 aopPut (AOP (result), zero, offset);
4920 // faster than result <- left, anl result,right
4921 // and better if result is SFR
4922 if (AOP_TYPE (left) == AOP_ACC)
4923 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4926 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4927 emitcode ("anl", "a,%s",
4928 aopGet (AOP (left), offset, FALSE, FALSE));
4930 aopPut (AOP (result), "a", offset);
4936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (result, NULL, ic, TRUE);
4941 /*-----------------------------------------------------------------*/
4942 /* genOr - code for or */
4943 /*-----------------------------------------------------------------*/
4945 genOr (iCode * ic, iCode * ifx)
4947 operand *left, *right, *result;
4948 int size, offset = 0;
4949 unsigned long lit = 0L;
4951 D(emitcode (";", "genOr"));
4953 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4954 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4955 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4958 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4960 AOP_TYPE (left), AOP_TYPE (right));
4961 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4963 AOP_SIZE (left), AOP_SIZE (right));
4966 /* if left is a literal & right is not then exchange them */
4967 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4968 AOP_NEEDSACC (left))
4970 operand *tmp = right;
4975 /* if result = right then exchange them */
4976 if (sameRegs (AOP (result), AOP (right)))
4978 operand *tmp = right;
4983 /* if right is bit then exchange them */
4984 if (AOP_TYPE (right) == AOP_CRY &&
4985 AOP_TYPE (left) != AOP_CRY)
4987 operand *tmp = right;
4991 if (AOP_TYPE (right) == AOP_LIT)
4992 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4994 size = AOP_SIZE (result);
4998 if (AOP_TYPE (left) == AOP_CRY)
5000 if (AOP_TYPE (right) == AOP_LIT)
5002 // c = bit | literal;
5005 // lit != 0 => result = 1
5006 if (AOP_TYPE (result) == AOP_CRY)
5009 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5011 continueIfTrue (ifx);
5014 emitcode ("setb", "c");
5018 // lit == 0 => result = left
5019 if (size && sameRegs (AOP (result), AOP (left)))
5021 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5026 if (AOP_TYPE (right) == AOP_CRY)
5029 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5030 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5035 symbol *tlbl = newiTempLabel (NULL);
5036 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5037 emitcode ("setb", "c");
5038 emitcode ("jb", "%s,%05d$",
5039 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5041 emitcode ("jnz", "%05d$", tlbl->key + 100);
5042 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5044 jmpTrueOrFalse (ifx, tlbl);
5050 emitcode ("", "%05d$:", tlbl->key + 100);
5059 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5060 genIfxJump (ifx, "c");
5064 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5065 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5066 if ((AOP_TYPE (right) == AOP_LIT) &&
5067 (AOP_TYPE (result) == AOP_CRY) &&
5068 (AOP_TYPE (left) != AOP_CRY))
5074 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5076 continueIfTrue (ifx);
5081 // lit = 0, result = boolean(left)
5083 emitcode ("setb", "c");
5087 symbol *tlbl = newiTempLabel (NULL);
5088 emitcode ("jnz", "%05d$", tlbl->key + 100);
5090 emitcode ("", "%05d$:", tlbl->key + 100);
5094 genIfxJump (ifx, "a");
5102 /* if left is same as result */
5103 if (sameRegs (AOP (result), AOP (left)))
5105 for (; size--; offset++)
5107 if (AOP_TYPE (right) == AOP_LIT)
5109 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5111 else if (IS_AOP_PREG (left))
5113 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5114 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5115 aopPut (AOP (result), "a", offset);
5118 emitcode ("orl", "%s,%s",
5119 aopGet (AOP (left), offset, FALSE, TRUE),
5120 aopGet (AOP (right), offset, FALSE, FALSE));
5124 if (AOP_TYPE (left) == AOP_ACC)
5125 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5128 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5129 if (IS_AOP_PREG (left))
5131 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5132 aopPut (AOP (result), "a", offset);
5135 emitcode ("orl", "%s,a",
5136 aopGet (AOP (left), offset, FALSE, TRUE));
5143 // left & result in different registers
5144 if (AOP_TYPE (result) == AOP_CRY)
5147 // if(size), result in bit
5148 // if(!size && ifx), conditional oper: if(left | right)
5149 symbol *tlbl = newiTempLabel (NULL);
5150 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5152 emitcode ("setb", "c");
5155 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5156 emitcode ("orl", "a,%s",
5157 aopGet (AOP (right), offset, FALSE, FALSE));
5159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5160 emitcode ("orl", "a,%s",
5161 aopGet (AOP (left), offset, FALSE, FALSE));
5163 emitcode ("jnz", "%05d$", tlbl->key + 100);
5169 emitcode ("", "%05d$:", tlbl->key + 100);
5173 jmpTrueOrFalse (ifx, tlbl);
5176 for (; (size--); offset++)
5179 // result = left & right
5180 if (AOP_TYPE (right) == AOP_LIT)
5182 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5184 aopPut (AOP (result),
5185 aopGet (AOP (left), offset, FALSE, FALSE),
5190 // faster than result <- left, anl result,right
5191 // and better if result is SFR
5192 if (AOP_TYPE (left) == AOP_ACC)
5193 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5196 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5197 emitcode ("orl", "a,%s",
5198 aopGet (AOP (left), offset, FALSE, FALSE));
5200 aopPut (AOP (result), "a", offset);
5205 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 freeAsmop (result, NULL, ic, TRUE);
5210 /*-----------------------------------------------------------------*/
5211 /* genXor - code for xclusive or */
5212 /*-----------------------------------------------------------------*/
5214 genXor (iCode * ic, iCode * ifx)
5216 operand *left, *right, *result;
5217 int size, offset = 0;
5218 unsigned long lit = 0L;
5220 D(emitcode (";", "genXor"));
5222 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5223 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5224 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5227 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5229 AOP_TYPE (left), AOP_TYPE (right));
5230 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5232 AOP_SIZE (left), AOP_SIZE (right));
5235 /* if left is a literal & right is not ||
5236 if left needs acc & right does not */
5237 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5238 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5240 operand *tmp = right;
5245 /* if result = right then exchange them */
5246 if (sameRegs (AOP (result), AOP (right)))
5248 operand *tmp = right;
5253 /* if right is bit then exchange them */
5254 if (AOP_TYPE (right) == AOP_CRY &&
5255 AOP_TYPE (left) != AOP_CRY)
5257 operand *tmp = right;
5261 if (AOP_TYPE (right) == AOP_LIT)
5262 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5264 size = AOP_SIZE (result);
5268 if (AOP_TYPE (left) == AOP_CRY)
5270 if (AOP_TYPE (right) == AOP_LIT)
5272 // c = bit & literal;
5275 // lit>>1 != 0 => result = 1
5276 if (AOP_TYPE (result) == AOP_CRY)
5279 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5281 continueIfTrue (ifx);
5284 emitcode ("setb", "c");
5291 // lit == 0, result = left
5292 if (size && sameRegs (AOP (result), AOP (left)))
5294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 // lit == 1, result = not(left)
5299 if (size && sameRegs (AOP (result), AOP (left)))
5301 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5306 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5307 emitcode ("cpl", "c");
5316 symbol *tlbl = newiTempLabel (NULL);
5317 if (AOP_TYPE (right) == AOP_CRY)
5320 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5324 int sizer = AOP_SIZE (right);
5326 // if val>>1 != 0, result = 1
5327 emitcode ("setb", "c");
5330 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5332 // test the msb of the lsb
5333 emitcode ("anl", "a,#0xfe");
5334 emitcode ("jnz", "%05d$", tlbl->key + 100);
5338 emitcode ("rrc", "a");
5340 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5341 emitcode ("cpl", "c");
5342 emitcode ("", "%05d$:", (tlbl->key + 100));
5349 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5350 genIfxJump (ifx, "c");
5354 if (sameRegs (AOP (result), AOP (left)))
5356 /* if left is same as result */
5357 for (; size--; offset++)
5359 if (AOP_TYPE (right) == AOP_LIT)
5361 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5363 else if (IS_AOP_PREG (left))
5365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5366 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5367 aopPut (AOP (result), "a", offset);
5370 emitcode ("xrl", "%s,%s",
5371 aopGet (AOP (left), offset, FALSE, TRUE),
5372 aopGet (AOP (right), offset, FALSE, FALSE));
5376 if (AOP_TYPE (left) == AOP_ACC)
5377 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5380 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5381 if (IS_AOP_PREG (left))
5383 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5384 aopPut (AOP (result), "a", offset);
5387 emitcode ("xrl", "%s,a",
5388 aopGet (AOP (left), offset, FALSE, TRUE));
5395 // left & result in different registers
5396 if (AOP_TYPE (result) == AOP_CRY)
5399 // if(size), result in bit
5400 // if(!size && ifx), conditional oper: if(left ^ right)
5401 symbol *tlbl = newiTempLabel (NULL);
5402 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5404 emitcode ("setb", "c");
5407 if ((AOP_TYPE (right) == AOP_LIT) &&
5408 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5410 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5414 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5415 emitcode ("xrl", "a,%s",
5416 aopGet (AOP (right), offset, FALSE, FALSE));
5418 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5419 emitcode ("xrl", "a,%s",
5420 aopGet (AOP (left), offset, FALSE, FALSE));
5423 emitcode ("jnz", "%05d$", tlbl->key + 100);
5429 emitcode ("", "%05d$:", tlbl->key + 100);
5433 jmpTrueOrFalse (ifx, tlbl);
5436 for (; (size--); offset++)
5439 // result = left & right
5440 if (AOP_TYPE (right) == AOP_LIT)
5442 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5444 aopPut (AOP (result),
5445 aopGet (AOP (left), offset, FALSE, FALSE),
5450 // faster than result <- left, anl result,right
5451 // and better if result is SFR
5452 if (AOP_TYPE (left) == AOP_ACC)
5453 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5456 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5457 emitcode ("xrl", "a,%s",
5458 aopGet (AOP (left), offset, FALSE, TRUE));
5460 aopPut (AOP (result), "a", offset);
5465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5467 freeAsmop (result, NULL, ic, TRUE);
5470 /*-----------------------------------------------------------------*/
5471 /* genInline - write the inline code out */
5472 /*-----------------------------------------------------------------*/
5474 genInline (iCode * ic)
5476 char *buffer, *bp, *bp1;
5478 D(emitcode (";", "genInline"));
5480 _G.inLine += (!options.asmpeep);
5482 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5483 strcpy (buffer, IC_INLINE (ic));
5485 /* emit each line as a code */
5510 /* emitcode("",buffer); */
5511 _G.inLine -= (!options.asmpeep);
5514 /*-----------------------------------------------------------------*/
5515 /* genRRC - rotate right with carry */
5516 /*-----------------------------------------------------------------*/
5520 operand *left, *result;
5521 int size, offset = 0;
5524 D(emitcode (";", "genRRC"));
5526 /* rotate right with carry */
5527 left = IC_LEFT (ic);
5528 result = IC_RESULT (ic);
5529 aopOp (left, ic, FALSE);
5530 aopOp (result, ic, FALSE);
5532 /* move it to the result */
5533 size = AOP_SIZE (result);
5535 if (size == 1) { /* special case for 1 byte */
5536 l = aopGet (AOP (left), offset, FALSE, FALSE);
5538 emitcode ("rr", "a");
5544 l = aopGet (AOP (left), offset, FALSE, FALSE);
5546 emitcode ("rrc", "a");
5547 if (AOP_SIZE (result) > 1)
5548 aopPut (AOP (result), "a", offset--);
5550 /* now we need to put the carry into the
5551 highest order byte of the result */
5552 if (AOP_SIZE (result) > 1)
5554 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5557 emitcode ("mov", "acc.7,c");
5559 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5560 freeAsmop (left, NULL, ic, TRUE);
5561 freeAsmop (result, NULL, ic, TRUE);
5564 /*-----------------------------------------------------------------*/
5565 /* genRLC - generate code for rotate left with carry */
5566 /*-----------------------------------------------------------------*/
5570 operand *left, *result;
5571 int size, offset = 0;
5574 D(emitcode (";", "genRLC"));
5576 /* rotate right with carry */
5577 left = IC_LEFT (ic);
5578 result = IC_RESULT (ic);
5579 aopOp (left, ic, FALSE);
5580 aopOp (result, ic, FALSE);
5582 /* move it to the result */
5583 size = AOP_SIZE (result);
5587 l = aopGet (AOP (left), offset, FALSE, FALSE);
5589 if (size == 0) { /* special case for 1 byte */
5593 emitcode ("add", "a,acc");
5594 if (AOP_SIZE (result) > 1)
5595 aopPut (AOP (result), "a", offset++);
5598 l = aopGet (AOP (left), offset, FALSE, FALSE);
5600 emitcode ("rlc", "a");
5601 if (AOP_SIZE (result) > 1)
5602 aopPut (AOP (result), "a", offset++);
5605 /* now we need to put the carry into the
5606 highest order byte of the result */
5607 if (AOP_SIZE (result) > 1)
5609 l = aopGet (AOP (result), 0, FALSE, FALSE);
5612 emitcode ("mov", "acc.0,c");
5614 aopPut (AOP (result), "a", 0);
5615 freeAsmop (left, NULL, ic, TRUE);
5616 freeAsmop (result, NULL, ic, TRUE);
5619 /*-----------------------------------------------------------------*/
5620 /* genGetHbit - generates code get highest order bit */
5621 /*-----------------------------------------------------------------*/
5623 genGetHbit (iCode * ic)
5625 operand *left, *result;
5627 D(emitcode (";", "genGetHbit"));
5629 left = IC_LEFT (ic);
5630 result = IC_RESULT (ic);
5631 aopOp (left, ic, FALSE);
5632 aopOp (result, ic, FALSE);
5634 /* get the highest order byte into a */
5635 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5636 if (AOP_TYPE (result) == AOP_CRY)
5638 emitcode ("rlc", "a");
5643 emitcode ("rl", "a");
5644 emitcode ("anl", "a,#0x01");
5649 freeAsmop (left, NULL, ic, TRUE);
5650 freeAsmop (result, NULL, ic, TRUE);
5653 /*-----------------------------------------------------------------*/
5654 /* AccRol - rotate left accumulator by known count */
5655 /*-----------------------------------------------------------------*/
5657 AccRol (int shCount)
5659 shCount &= 0x0007; // shCount : 0..7
5666 emitcode ("rl", "a");
5669 emitcode ("rl", "a");
5670 emitcode ("rl", "a");
5673 emitcode ("swap", "a");
5674 emitcode ("rr", "a");
5677 emitcode ("swap", "a");
5680 emitcode ("swap", "a");
5681 emitcode ("rl", "a");
5684 emitcode ("rr", "a");
5685 emitcode ("rr", "a");
5688 emitcode ("rr", "a");
5693 /*-----------------------------------------------------------------*/
5694 /* AccLsh - left shift accumulator by known count */
5695 /*-----------------------------------------------------------------*/
5697 AccLsh (int shCount)
5702 emitcode ("add", "a,acc");
5703 else if (shCount == 2)
5705 emitcode ("add", "a,acc");
5706 emitcode ("add", "a,acc");
5710 /* rotate left accumulator */
5712 /* and kill the lower order bits */
5713 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5718 /*-----------------------------------------------------------------*/
5719 /* AccRsh - right shift accumulator by known count */
5720 /*-----------------------------------------------------------------*/
5722 AccRsh (int shCount)
5729 emitcode ("rrc", "a");
5733 /* rotate right accumulator */
5734 AccRol (8 - shCount);
5735 /* and kill the higher order bits */
5736 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5741 /*-----------------------------------------------------------------*/
5742 /* AccSRsh - signed right shift accumulator by known count */
5743 /*-----------------------------------------------------------------*/
5745 AccSRsh (int shCount)
5752 emitcode ("mov", "c,acc.7");
5753 emitcode ("rrc", "a");
5755 else if (shCount == 2)
5757 emitcode ("mov", "c,acc.7");
5758 emitcode ("rrc", "a");
5759 emitcode ("mov", "c,acc.7");
5760 emitcode ("rrc", "a");
5764 tlbl = newiTempLabel (NULL);
5765 /* rotate right accumulator */
5766 AccRol (8 - shCount);
5767 /* and kill the higher order bits */
5768 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5769 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5770 emitcode ("orl", "a,#0x%02x",
5771 (unsigned char) ~SRMask[shCount]);
5772 emitcode ("", "%05d$:", tlbl->key + 100);
5777 /*-----------------------------------------------------------------*/
5778 /* shiftR1Left2Result - shift right one byte from left to result */
5779 /*-----------------------------------------------------------------*/
5781 shiftR1Left2Result (operand * left, int offl,
5782 operand * result, int offr,
5783 int shCount, int sign)
5785 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5786 /* shift right accumulator */
5791 aopPut (AOP (result), "a", offr);
5794 /*-----------------------------------------------------------------*/
5795 /* shiftL1Left2Result - shift left one byte from left to result */
5796 /*-----------------------------------------------------------------*/
5798 shiftL1Left2Result (operand * left, int offl,
5799 operand * result, int offr, int shCount)
5802 l = aopGet (AOP (left), offl, FALSE, FALSE);
5804 /* shift left accumulator */
5806 aopPut (AOP (result), "a", offr);
5809 /*-----------------------------------------------------------------*/
5810 /* movLeft2Result - move byte from left to result */
5811 /*-----------------------------------------------------------------*/
5813 movLeft2Result (operand * left, int offl,
5814 operand * result, int offr, int sign)
5817 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5819 l = aopGet (AOP (left), offl, FALSE, FALSE);
5821 if (*l == '@' && (IS_AOP_PREG (result)))
5823 emitcode ("mov", "a,%s", l);
5824 aopPut (AOP (result), "a", offr);
5829 aopPut (AOP (result), l, offr);
5832 /* MSB sign in acc.7 ! */
5833 if (getDataSize (left) == offl + 1)
5835 emitcode ("mov", "a,%s", l);
5836 aopPut (AOP (result), "a", offr);
5843 /*-----------------------------------------------------------------*/
5844 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5845 /*-----------------------------------------------------------------*/
5849 emitcode ("rrc", "a");
5850 emitcode ("xch", "a,%s", x);
5851 emitcode ("rrc", "a");
5852 emitcode ("xch", "a,%s", x);
5855 /*-----------------------------------------------------------------*/
5856 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5857 /*-----------------------------------------------------------------*/
5861 emitcode ("xch", "a,%s", x);
5862 emitcode ("rlc", "a");
5863 emitcode ("xch", "a,%s", x);
5864 emitcode ("rlc", "a");
5867 /*-----------------------------------------------------------------*/
5868 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5869 /*-----------------------------------------------------------------*/
5873 emitcode ("xch", "a,%s", x);
5874 emitcode ("add", "a,acc");
5875 emitcode ("xch", "a,%s", x);
5876 emitcode ("rlc", "a");
5879 /*-----------------------------------------------------------------*/
5880 /* AccAXLsh - left shift a:x by known count (0..7) */
5881 /*-----------------------------------------------------------------*/
5883 AccAXLsh (char *x, int shCount)
5898 case 5: // AAAAABBB:CCCCCDDD
5900 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5902 emitcode ("anl", "a,#0x%02x",
5903 SLMask[shCount]); // BBB00000:CCCCCDDD
5905 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5907 AccRol (shCount); // DDDCCCCC:BBB00000
5909 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5911 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5913 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5915 emitcode ("anl", "a,#0x%02x",
5916 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5918 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5920 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5923 case 6: // AAAAAABB:CCCCCCDD
5924 emitcode ("anl", "a,#0x%02x",
5925 SRMask[shCount]); // 000000BB:CCCCCCDD
5926 emitcode ("mov", "c,acc.0"); // c = B
5927 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5929 AccAXRrl1 (x); // BCCCCCCD:D000000B
5930 AccAXRrl1 (x); // BBCCCCCC:DD000000
5932 emitcode("rrc","a");
5933 emitcode("xch","a,%s", x);
5934 emitcode("rrc","a");
5935 emitcode("mov","c,acc.0"); //<< get correct bit
5936 emitcode("xch","a,%s", x);
5938 emitcode("rrc","a");
5939 emitcode("xch","a,%s", x);
5940 emitcode("rrc","a");
5941 emitcode("xch","a,%s", x);
5944 case 7: // a:x <<= 7
5946 emitcode ("anl", "a,#0x%02x",
5947 SRMask[shCount]); // 0000000B:CCCCCCCD
5949 emitcode ("mov", "c,acc.0"); // c = B
5951 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5953 AccAXRrl1 (x); // BCCCCCCC:D0000000
5961 /*-----------------------------------------------------------------*/
5962 /* AccAXRsh - right shift a:x known count (0..7) */
5963 /*-----------------------------------------------------------------*/
5965 AccAXRsh (char *x, int shCount)
5973 AccAXRrl1 (x); // 0->a:x
5978 AccAXRrl1 (x); // 0->a:x
5981 AccAXRrl1 (x); // 0->a:x
5986 case 5: // AAAAABBB:CCCCCDDD = a:x
5988 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5990 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5992 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5994 emitcode ("anl", "a,#0x%02x",
5995 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5997 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5999 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6001 emitcode ("anl", "a,#0x%02x",
6002 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6004 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6006 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6008 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6011 case 6: // AABBBBBB:CCDDDDDD
6013 emitcode ("mov", "c,acc.7");
6014 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6016 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6018 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6020 emitcode ("anl", "a,#0x%02x",
6021 SRMask[shCount]); // 000000AA:BBBBBBCC
6024 case 7: // ABBBBBBB:CDDDDDDD
6026 emitcode ("mov", "c,acc.7"); // c = A
6028 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6030 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6032 emitcode ("anl", "a,#0x%02x",
6033 SRMask[shCount]); // 0000000A:BBBBBBBC
6041 /*-----------------------------------------------------------------*/
6042 /* AccAXRshS - right shift signed a:x known count (0..7) */
6043 /*-----------------------------------------------------------------*/
6045 AccAXRshS (char *x, int shCount)
6053 emitcode ("mov", "c,acc.7");
6054 AccAXRrl1 (x); // s->a:x
6058 emitcode ("mov", "c,acc.7");
6059 AccAXRrl1 (x); // s->a:x
6061 emitcode ("mov", "c,acc.7");
6062 AccAXRrl1 (x); // s->a:x
6067 case 5: // AAAAABBB:CCCCCDDD = a:x
6069 tlbl = newiTempLabel (NULL);
6070 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6072 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6074 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6076 emitcode ("anl", "a,#0x%02x",
6077 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6079 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6081 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6083 emitcode ("anl", "a,#0x%02x",
6084 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6086 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6088 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6090 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6092 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6093 emitcode ("orl", "a,#0x%02x",
6094 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6096 emitcode ("", "%05d$:", tlbl->key + 100);
6097 break; // SSSSAAAA:BBBCCCCC
6099 case 6: // AABBBBBB:CCDDDDDD
6101 tlbl = newiTempLabel (NULL);
6102 emitcode ("mov", "c,acc.7");
6103 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6105 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6107 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6109 emitcode ("anl", "a,#0x%02x",
6110 SRMask[shCount]); // 000000AA:BBBBBBCC
6112 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6113 emitcode ("orl", "a,#0x%02x",
6114 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6116 emitcode ("", "%05d$:", tlbl->key + 100);
6118 case 7: // ABBBBBBB:CDDDDDDD
6120 tlbl = newiTempLabel (NULL);
6121 emitcode ("mov", "c,acc.7"); // c = A
6123 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6125 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6127 emitcode ("anl", "a,#0x%02x",
6128 SRMask[shCount]); // 0000000A:BBBBBBBC
6130 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6131 emitcode ("orl", "a,#0x%02x",
6132 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6134 emitcode ("", "%05d$:", tlbl->key + 100);
6141 /*-----------------------------------------------------------------*/
6142 /* shiftL2Left2Result - shift left two bytes from left to result */
6143 /*-----------------------------------------------------------------*/
6145 shiftL2Left2Result (operand * left, int offl,
6146 operand * result, int offr, int shCount)
6148 if (sameRegs (AOP (result), AOP (left)) &&
6149 ((offl + MSB16) == offr))
6151 /* don't crash result[offr] */
6152 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6153 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6157 movLeft2Result (left, offl, result, offr, 0);
6158 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6160 /* ax << shCount (x = lsb(result)) */
6161 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6162 aopPut (AOP (result), "a", offr + MSB16);
6166 /*-----------------------------------------------------------------*/
6167 /* shiftR2Left2Result - shift right two bytes from left to result */
6168 /*-----------------------------------------------------------------*/
6170 shiftR2Left2Result (operand * left, int offl,
6171 operand * result, int offr,
6172 int shCount, int sign)
6174 if (sameRegs (AOP (result), AOP (left)) &&
6175 ((offl + MSB16) == offr))
6177 /* don't crash result[offr] */
6178 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6179 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6183 movLeft2Result (left, offl, result, offr, 0);
6184 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6186 /* a:x >> shCount (x = lsb(result)) */
6188 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6190 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6191 if (getDataSize (result) > 1)
6192 aopPut (AOP (result), "a", offr + MSB16);
6195 /*-----------------------------------------------------------------*/
6196 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6197 /*-----------------------------------------------------------------*/
6199 shiftLLeftOrResult (operand * left, int offl,
6200 operand * result, int offr, int shCount)
6202 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6203 /* shift left accumulator */
6205 /* or with result */
6206 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6207 /* back to result */
6208 aopPut (AOP (result), "a", offr);
6211 /*-----------------------------------------------------------------*/
6212 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6213 /*-----------------------------------------------------------------*/
6215 shiftRLeftOrResult (operand * left, int offl,
6216 operand * result, int offr, int shCount)
6218 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6219 /* shift right accumulator */
6221 /* or with result */
6222 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6223 /* back to result */
6224 aopPut (AOP (result), "a", offr);
6227 /*-----------------------------------------------------------------*/
6228 /* genlshOne - left shift a one byte quantity by known count */
6229 /*-----------------------------------------------------------------*/
6231 genlshOne (operand * result, operand * left, int shCount)
6233 D(emitcode (";", "genlshOne"));
6235 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6238 /*-----------------------------------------------------------------*/
6239 /* genlshTwo - left shift two bytes by known amount != 0 */
6240 /*-----------------------------------------------------------------*/
6242 genlshTwo (operand * result, operand * left, int shCount)
6246 D(emitcode (";", "genlshTwo"));
6248 size = getDataSize (result);
6250 /* if shCount >= 8 */
6258 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6260 movLeft2Result (left, LSB, result, MSB16, 0);
6262 aopPut (AOP (result), zero, LSB);
6265 /* 1 <= shCount <= 7 */
6269 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6271 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6275 /*-----------------------------------------------------------------*/
6276 /* shiftLLong - shift left one long from left to result */
6277 /* offl = LSB or MSB16 */
6278 /*-----------------------------------------------------------------*/
6280 shiftLLong (operand * left, operand * result, int offr)
6283 int size = AOP_SIZE (result);
6285 if (size >= LSB + offr)
6287 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6289 emitcode ("add", "a,acc");
6290 if (sameRegs (AOP (left), AOP (result)) &&
6291 size >= MSB16 + offr && offr != LSB)
6292 emitcode ("xch", "a,%s",
6293 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6295 aopPut (AOP (result), "a", LSB + offr);
6298 if (size >= MSB16 + offr)
6300 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6302 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6305 emitcode ("rlc", "a");
6306 if (sameRegs (AOP (left), AOP (result)) &&
6307 size >= MSB24 + offr && offr != LSB)
6308 emitcode ("xch", "a,%s",
6309 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6311 aopPut (AOP (result), "a", MSB16 + offr);
6314 if (size >= MSB24 + offr)
6316 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6318 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6321 emitcode ("rlc", "a");
6322 if (sameRegs (AOP (left), AOP (result)) &&
6323 size >= MSB32 + offr && offr != LSB)
6324 emitcode ("xch", "a,%s",
6325 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6327 aopPut (AOP (result), "a", MSB24 + offr);
6330 if (size > MSB32 + offr)
6332 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6334 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6337 emitcode ("rlc", "a");
6338 aopPut (AOP (result), "a", MSB32 + offr);
6341 aopPut (AOP (result), zero, LSB);
6344 /*-----------------------------------------------------------------*/
6345 /* genlshFour - shift four byte by a known amount != 0 */
6346 /*-----------------------------------------------------------------*/
6348 genlshFour (operand * result, operand * left, int shCount)
6352 D(emitcode (";", "genlshFour"));
6354 size = AOP_SIZE (result);
6356 /* if shifting more that 3 bytes */
6361 /* lowest order of left goes to the highest
6362 order of the destination */
6363 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6365 movLeft2Result (left, LSB, result, MSB32, 0);
6366 aopPut (AOP (result), zero, LSB);
6367 aopPut (AOP (result), zero, MSB16);
6368 aopPut (AOP (result), zero, MSB24);
6372 /* more than two bytes */
6373 else if (shCount >= 16)
6375 /* lower order two bytes goes to higher order two bytes */
6377 /* if some more remaining */
6379 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6382 movLeft2Result (left, MSB16, result, MSB32, 0);
6383 movLeft2Result (left, LSB, result, MSB24, 0);
6385 aopPut (AOP (result), zero, MSB16);
6386 aopPut (AOP (result), zero, LSB);
6390 /* if more than 1 byte */
6391 else if (shCount >= 8)
6393 /* lower order three bytes goes to higher order three bytes */
6398 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6400 movLeft2Result (left, LSB, result, MSB16, 0);
6406 movLeft2Result (left, MSB24, result, MSB32, 0);
6407 movLeft2Result (left, MSB16, result, MSB24, 0);
6408 movLeft2Result (left, LSB, result, MSB16, 0);
6409 aopPut (AOP (result), zero, LSB);
6411 else if (shCount == 1)
6412 shiftLLong (left, result, MSB16);
6415 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6416 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6417 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6418 aopPut (AOP (result), zero, LSB);
6423 /* 1 <= shCount <= 7 */
6424 else if (shCount <= 2)
6426 shiftLLong (left, result, LSB);
6428 shiftLLong (result, result, LSB);
6430 /* 3 <= shCount <= 7, optimize */
6433 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6434 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6435 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6439 /*-----------------------------------------------------------------*/
6440 /* genLeftShiftLiteral - left shifting by known count */
6441 /*-----------------------------------------------------------------*/
6443 genLeftShiftLiteral (operand * left,
6448 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6451 D(emitcode (";", "genLeftShiftLiteral"));
6453 freeAsmop (right, NULL, ic, TRUE);
6455 aopOp (left, ic, FALSE);
6456 aopOp (result, ic, FALSE);
6458 size = getSize (operandType (result));
6461 emitcode ("; shift left ", "result %d, left %d", size,
6465 /* I suppose that the left size >= result size */
6470 movLeft2Result (left, size, result, size, 0);
6474 else if (shCount >= (size * 8))
6476 aopPut (AOP (result), zero, size);
6482 genlshOne (result, left, shCount);
6486 genlshTwo (result, left, shCount);
6490 genlshFour (result, left, shCount);
6493 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6494 "*** ack! mystery literal shift!\n");
6498 freeAsmop (left, NULL, ic, TRUE);
6499 freeAsmop (result, NULL, ic, TRUE);
6502 /*-----------------------------------------------------------------*/
6503 /* genLeftShift - generates code for left shifting */
6504 /*-----------------------------------------------------------------*/
6506 genLeftShift (iCode * ic)
6508 operand *left, *right, *result;
6511 symbol *tlbl, *tlbl1;
6513 D(emitcode (";", "genLeftShift"));
6515 right = IC_RIGHT (ic);
6516 left = IC_LEFT (ic);
6517 result = IC_RESULT (ic);
6519 aopOp (right, ic, FALSE);
6521 /* if the shift count is known then do it
6522 as efficiently as possible */
6523 if (AOP_TYPE (right) == AOP_LIT)
6525 genLeftShiftLiteral (left, right, result, ic);
6529 /* shift count is unknown then we have to form
6530 a loop get the loop count in B : Note: we take
6531 only the lower order byte since shifting
6532 more that 32 bits make no sense anyway, ( the
6533 largest size of an object can be only 32 bits ) */
6535 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6536 emitcode ("inc", "b");
6537 freeAsmop (right, NULL, ic, TRUE);
6538 aopOp (left, ic, FALSE);
6539 aopOp (result, ic, FALSE);
6541 /* now move the left to the result if they are not the
6543 if (!sameRegs (AOP (left), AOP (result)) &&
6544 AOP_SIZE (result) > 1)
6547 size = AOP_SIZE (result);
6551 l = aopGet (AOP (left), offset, FALSE, TRUE);
6552 if (*l == '@' && (IS_AOP_PREG (result)))
6555 emitcode ("mov", "a,%s", l);
6556 aopPut (AOP (result), "a", offset);
6559 aopPut (AOP (result), l, offset);
6564 tlbl = newiTempLabel (NULL);
6565 size = AOP_SIZE (result);
6567 tlbl1 = newiTempLabel (NULL);
6569 /* if it is only one byte then */
6572 symbol *tlbl1 = newiTempLabel (NULL);
6574 l = aopGet (AOP (left), 0, FALSE, FALSE);
6576 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6577 emitcode ("", "%05d$:", tlbl->key + 100);
6578 emitcode ("add", "a,acc");
6579 emitcode ("", "%05d$:", tlbl1->key + 100);
6580 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6581 aopPut (AOP (result), "a", 0);
6585 reAdjustPreg (AOP (result));
6587 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6588 emitcode ("", "%05d$:", tlbl->key + 100);
6589 l = aopGet (AOP (result), offset, FALSE, FALSE);
6591 emitcode ("add", "a,acc");
6592 aopPut (AOP (result), "a", offset++);
6595 l = aopGet (AOP (result), offset, FALSE, FALSE);
6597 emitcode ("rlc", "a");
6598 aopPut (AOP (result), "a", offset++);
6600 reAdjustPreg (AOP (result));
6602 emitcode ("", "%05d$:", tlbl1->key + 100);
6603 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6605 freeAsmop (left, NULL, ic, TRUE);
6606 freeAsmop (result, NULL, ic, TRUE);
6609 /*-----------------------------------------------------------------*/
6610 /* genrshOne - right shift a one byte quantity by known count */
6611 /*-----------------------------------------------------------------*/
6613 genrshOne (operand * result, operand * left,
6614 int shCount, int sign)
6616 D(emitcode (";", "genrshOne"));
6618 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6621 /*-----------------------------------------------------------------*/
6622 /* genrshTwo - right shift two bytes by known amount != 0 */
6623 /*-----------------------------------------------------------------*/
6625 genrshTwo (operand * result, operand * left,
6626 int shCount, int sign)
6628 D(emitcode (";", "genrshTwo"));
6630 /* if shCount >= 8 */
6635 shiftR1Left2Result (left, MSB16, result, LSB,
6638 movLeft2Result (left, MSB16, result, LSB, sign);
6639 addSign (result, MSB16, sign);
6642 /* 1 <= shCount <= 7 */
6644 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6647 /*-----------------------------------------------------------------*/
6648 /* shiftRLong - shift right one long from left to result */
6649 /* offl = LSB or MSB16 */
6650 /*-----------------------------------------------------------------*/
6652 shiftRLong (operand * left, int offl,
6653 operand * result, int sign)
6655 int isSameRegs=sameRegs(AOP(left),AOP(result));
6657 if (isSameRegs && offl>1) {
6658 // we are in big trouble, but this shouldn't happen
6659 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6662 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6667 emitcode ("rlc", "a");
6668 emitcode ("subb", "a,acc");
6669 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6671 aopPut (AOP(result), zero, MSB32);
6676 emitcode ("clr", "c");
6678 emitcode ("mov", "c,acc.7");
6681 emitcode ("rrc", "a");
6683 if (isSameRegs && offl==MSB16) {
6684 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6686 aopPut (AOP (result), "a", MSB32);
6687 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6690 emitcode ("rrc", "a");
6691 if (isSameRegs && offl==1) {
6692 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6694 aopPut (AOP (result), "a", MSB24);
6695 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6697 emitcode ("rrc", "a");
6698 aopPut (AOP (result), "a", MSB16 - offl);
6702 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6703 emitcode ("rrc", "a");
6704 aopPut (AOP (result), "a", LSB);
6708 /*-----------------------------------------------------------------*/
6709 /* genrshFour - shift four byte by a known amount != 0 */
6710 /*-----------------------------------------------------------------*/
6712 genrshFour (operand * result, operand * left,
6713 int shCount, int sign)
6715 D(emitcode (";", "genrshFour"));
6717 /* if shifting more that 3 bytes */
6722 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6724 movLeft2Result (left, MSB32, result, LSB, sign);
6725 addSign (result, MSB16, sign);
6727 else if (shCount >= 16)
6731 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6734 movLeft2Result (left, MSB24, result, LSB, 0);
6735 movLeft2Result (left, MSB32, result, MSB16, sign);
6737 addSign (result, MSB24, sign);
6739 else if (shCount >= 8)
6743 shiftRLong (left, MSB16, result, sign);
6744 else if (shCount == 0)
6746 movLeft2Result (left, MSB16, result, LSB, 0);
6747 movLeft2Result (left, MSB24, result, MSB16, 0);
6748 movLeft2Result (left, MSB32, result, MSB24, sign);
6749 addSign (result, MSB32, sign);
6753 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6754 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6755 /* the last shift is signed */
6756 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6757 addSign (result, MSB32, sign);
6761 { /* 1 <= shCount <= 7 */
6764 shiftRLong (left, LSB, result, sign);
6766 shiftRLong (result, LSB, result, sign);
6770 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6771 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6772 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6777 /*-----------------------------------------------------------------*/
6778 /* genRightShiftLiteral - right shifting by known count */
6779 /*-----------------------------------------------------------------*/
6781 genRightShiftLiteral (operand * left,
6787 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6790 D(emitcode (";", "genRightShiftLiteral"));
6792 freeAsmop (right, NULL, ic, TRUE);
6794 aopOp (left, ic, FALSE);
6795 aopOp (result, ic, FALSE);
6798 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6802 size = getDataSize (left);
6803 /* test the LEFT size !!! */
6805 /* I suppose that the left size >= result size */
6808 size = getDataSize (result);
6810 movLeft2Result (left, size, result, size, 0);
6813 else if (shCount >= (size * 8))
6816 /* get sign in acc.7 */
6817 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6818 addSign (result, LSB, sign);
6825 genrshOne (result, left, shCount, sign);
6829 genrshTwo (result, left, shCount, sign);
6833 genrshFour (result, left, shCount, sign);
6839 freeAsmop (left, NULL, ic, TRUE);
6840 freeAsmop (result, NULL, ic, TRUE);
6844 /*-----------------------------------------------------------------*/
6845 /* genSignedRightShift - right shift of signed number */
6846 /*-----------------------------------------------------------------*/
6848 genSignedRightShift (iCode * ic)
6850 operand *right, *left, *result;
6853 symbol *tlbl, *tlbl1;
6855 D(emitcode (";", "genSignedRightShift"));
6857 /* we do it the hard way put the shift count in b
6858 and loop thru preserving the sign */
6860 right = IC_RIGHT (ic);
6861 left = IC_LEFT (ic);
6862 result = IC_RESULT (ic);
6864 aopOp (right, ic, FALSE);
6867 if (AOP_TYPE (right) == AOP_LIT)
6869 genRightShiftLiteral (left, right, result, ic, 1);
6872 /* shift count is unknown then we have to form
6873 a loop get the loop count in B : Note: we take
6874 only the lower order byte since shifting
6875 more that 32 bits make no sense anyway, ( the
6876 largest size of an object can be only 32 bits ) */
6878 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6879 emitcode ("inc", "b");
6880 freeAsmop (right, NULL, ic, TRUE);
6881 aopOp (left, ic, FALSE);
6882 aopOp (result, ic, FALSE);
6884 /* now move the left to the result if they are not the
6886 if (!sameRegs (AOP (left), AOP (result)) &&
6887 AOP_SIZE (result) > 1)
6890 size = AOP_SIZE (result);
6894 l = aopGet (AOP (left), offset, FALSE, TRUE);
6895 if (*l == '@' && IS_AOP_PREG (result))
6898 emitcode ("mov", "a,%s", l);
6899 aopPut (AOP (result), "a", offset);
6902 aopPut (AOP (result), l, offset);
6907 /* mov the highest order bit to OVR */
6908 tlbl = newiTempLabel (NULL);
6909 tlbl1 = newiTempLabel (NULL);
6911 size = AOP_SIZE (result);
6913 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6914 emitcode ("rlc", "a");
6915 emitcode ("mov", "ov,c");
6916 /* if it is only one byte then */
6919 l = aopGet (AOP (left), 0, FALSE, FALSE);
6921 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6922 emitcode ("", "%05d$:", tlbl->key + 100);
6923 emitcode ("mov", "c,ov");
6924 emitcode ("rrc", "a");
6925 emitcode ("", "%05d$:", tlbl1->key + 100);
6926 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6927 aopPut (AOP (result), "a", 0);
6931 reAdjustPreg (AOP (result));
6932 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6933 emitcode ("", "%05d$:", tlbl->key + 100);
6934 emitcode ("mov", "c,ov");
6937 l = aopGet (AOP (result), offset, FALSE, FALSE);
6939 emitcode ("rrc", "a");
6940 aopPut (AOP (result), "a", offset--);
6942 reAdjustPreg (AOP (result));
6943 emitcode ("", "%05d$:", tlbl1->key + 100);
6944 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6947 freeAsmop (left, NULL, ic, TRUE);
6948 freeAsmop (result, NULL, ic, TRUE);
6951 /*-----------------------------------------------------------------*/
6952 /* genRightShift - generate code for right shifting */
6953 /*-----------------------------------------------------------------*/
6955 genRightShift (iCode * ic)
6957 operand *right, *left, *result;
6961 symbol *tlbl, *tlbl1;
6963 D(emitcode (";", "genRightShift"));
6965 /* if signed then we do it the hard way preserve the
6966 sign bit moving it inwards */
6967 retype = getSpec (operandType (IC_RESULT (ic)));
6969 if (!SPEC_USIGN (retype))
6971 genSignedRightShift (ic);
6975 /* signed & unsigned types are treated the same : i.e. the
6976 signed is NOT propagated inwards : quoting from the
6977 ANSI - standard : "for E1 >> E2, is equivalent to division
6978 by 2**E2 if unsigned or if it has a non-negative value,
6979 otherwise the result is implementation defined ", MY definition
6980 is that the sign does not get propagated */
6982 right = IC_RIGHT (ic);
6983 left = IC_LEFT (ic);
6984 result = IC_RESULT (ic);
6986 aopOp (right, ic, FALSE);
6988 /* if the shift count is known then do it
6989 as efficiently as possible */
6990 if (AOP_TYPE (right) == AOP_LIT)
6992 genRightShiftLiteral (left, right, result, ic, 0);
6996 /* shift count is unknown then we have to form
6997 a loop get the loop count in B : Note: we take
6998 only the lower order byte since shifting
6999 more that 32 bits make no sense anyway, ( the
7000 largest size of an object can be only 32 bits ) */
7002 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7003 emitcode ("inc", "b");
7004 freeAsmop (right, NULL, ic, TRUE);
7005 aopOp (left, ic, FALSE);
7006 aopOp (result, ic, FALSE);
7008 /* now move the left to the result if they are not the
7010 if (!sameRegs (AOP (left), AOP (result)) &&
7011 AOP_SIZE (result) > 1)
7014 size = AOP_SIZE (result);
7018 l = aopGet (AOP (left), offset, FALSE, TRUE);
7019 if (*l == '@' && IS_AOP_PREG (result))
7022 emitcode ("mov", "a,%s", l);
7023 aopPut (AOP (result), "a", offset);
7026 aopPut (AOP (result), l, offset);
7031 tlbl = newiTempLabel (NULL);
7032 tlbl1 = newiTempLabel (NULL);
7033 size = AOP_SIZE (result);
7036 /* if it is only one byte then */
7039 l = aopGet (AOP (left), 0, FALSE, FALSE);
7041 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7042 emitcode ("", "%05d$:", tlbl->key + 100);
7044 emitcode ("rrc", "a");
7045 emitcode ("", "%05d$:", tlbl1->key + 100);
7046 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7047 aopPut (AOP (result), "a", 0);
7051 reAdjustPreg (AOP (result));
7052 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7053 emitcode ("", "%05d$:", tlbl->key + 100);
7057 l = aopGet (AOP (result), offset, FALSE, FALSE);
7059 emitcode ("rrc", "a");
7060 aopPut (AOP (result), "a", offset--);
7062 reAdjustPreg (AOP (result));
7064 emitcode ("", "%05d$:", tlbl1->key + 100);
7065 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7068 freeAsmop (left, NULL, ic, TRUE);
7069 freeAsmop (result, NULL, ic, TRUE);
7072 /*-----------------------------------------------------------------*/
7073 /* genUnpackBits - generates code for unpacking bits */
7074 /*-----------------------------------------------------------------*/
7076 genUnpackBits (operand * result, char *rname, int ptype)
7084 D(emitcode (";", "genUnpackBits"));
7086 etype = getSpec (operandType (result));
7087 rsize = getSize (operandType (result));
7088 /* read the first byte */
7094 emitcode ("mov", "a,@%s", rname);
7098 emitcode ("movx", "a,@%s", rname);
7102 emitcode ("movx", "a,@dptr");
7106 emitcode ("clr", "a");
7107 emitcode ("movc", "a,@a+dptr");
7111 emitcode ("lcall", "__gptrget");
7115 rlen = SPEC_BLEN (etype);
7117 /* if we have bitdisplacement then it fits */
7118 /* into this byte completely or if length is */
7119 /* less than a byte */
7120 if ((shCnt = SPEC_BSTR (etype)) ||
7121 (SPEC_BLEN (etype) <= 8))
7124 /* shift right acc */
7127 emitcode ("anl", "a,#0x%02x",
7128 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7129 aopPut (AOP (result), "a", offset++);
7133 /* bit field did not fit in a byte */
7134 aopPut (AOP (result), "a", offset++);
7143 emitcode ("inc", "%s", rname);
7144 emitcode ("mov", "a,@%s", rname);
7148 emitcode ("inc", "%s", rname);
7149 emitcode ("movx", "a,@%s", rname);
7153 emitcode ("inc", "dptr");
7154 emitcode ("movx", "a,@dptr");
7158 emitcode ("clr", "a");
7159 emitcode ("inc", "dptr");
7160 emitcode ("movc", "a,@a+dptr");
7164 emitcode ("inc", "dptr");
7165 emitcode ("lcall", "__gptrget");
7170 /* if we are done */
7174 aopPut (AOP (result), "a", offset++);
7180 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7182 aopPut (AOP (result), "a", offset++);
7190 aopPut (AOP (result), zero, offset++);
7196 /*-----------------------------------------------------------------*/
7197 /* genDataPointerGet - generates code when ptr offset is known */
7198 /*-----------------------------------------------------------------*/
7200 genDataPointerGet (operand * left,
7206 int size, offset = 0;
7208 D(emitcode (";", "genDataPointerGet"));
7210 aopOp (result, ic, TRUE);
7212 /* get the string representation of the name */
7213 l = aopGet (AOP (left), 0, FALSE, TRUE);
7214 size = AOP_SIZE (result);
7218 sprintf (buffer, "(%s + %d)", l + 1, offset);
7220 sprintf (buffer, "%s", l + 1);
7221 aopPut (AOP (result), buffer, offset++);
7224 freeAsmop (left, NULL, ic, TRUE);
7225 freeAsmop (result, NULL, ic, TRUE);
7228 /*-----------------------------------------------------------------*/
7229 /* genNearPointerGet - emitcode for near pointer fetch */
7230 /*-----------------------------------------------------------------*/
7232 genNearPointerGet (operand * left,
7240 sym_link *rtype, *retype;
7241 sym_link *ltype = operandType (left);
7244 D(emitcode (";", "genNearPointerGet"));
7246 rtype = operandType (result);
7247 retype = getSpec (rtype);
7249 aopOp (left, ic, FALSE);
7251 /* if left is rematerialisable and
7252 result is not bit variable type and
7253 the left is pointer to data space i.e
7254 lower 128 bytes of space */
7255 if (AOP_TYPE (left) == AOP_IMMD &&
7256 !IS_BITVAR (retype) &&
7257 DCL_TYPE (ltype) == POINTER)
7259 genDataPointerGet (left, result, ic);
7263 /* if the value is already in a pointer register
7264 then don't need anything more */
7265 if (!AOP_INPREG (AOP (left)))
7267 /* otherwise get a free pointer register */
7269 preg = getFreePtr (ic, &aop, FALSE);
7270 emitcode ("mov", "%s,%s",
7272 aopGet (AOP (left), 0, FALSE, TRUE));
7276 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7278 //aopOp (result, ic, FALSE);
7279 aopOp (result, ic, result?TRUE:FALSE);
7281 /* if bitfield then unpack the bits */
7282 if (IS_BITVAR (retype))
7283 genUnpackBits (result, rname, POINTER);
7286 /* we have can just get the values */
7287 int size = AOP_SIZE (result);
7292 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7295 emitcode ("mov", "a,@%s", rname);
7296 aopPut (AOP (result), "a", offset);
7300 sprintf (buffer, "@%s", rname);
7301 aopPut (AOP (result), buffer, offset);
7305 emitcode ("inc", "%s", rname);
7309 /* now some housekeeping stuff */
7310 if (aop) /* we had to allocate for this iCode */
7312 if (pi) { /* post increment present */
7313 aopPut(AOP ( left ),rname,0);
7315 freeAsmop (NULL, aop, ic, TRUE);
7319 /* we did not allocate which means left
7320 already in a pointer register, then
7321 if size > 0 && this could be used again
7322 we have to point it back to where it
7324 if ((AOP_SIZE (result) > 1 &&
7325 !OP_SYMBOL (left)->remat &&
7326 (OP_SYMBOL (left)->liveTo > ic->seq ||
7330 int size = AOP_SIZE (result) - 1;
7332 emitcode ("dec", "%s", rname);
7337 freeAsmop (left, NULL, ic, TRUE);
7338 freeAsmop (result, NULL, ic, TRUE);
7339 if (pi) pi->generated = 1;
7342 /*-----------------------------------------------------------------*/
7343 /* genPagedPointerGet - emitcode for paged pointer fetch */
7344 /*-----------------------------------------------------------------*/
7346 genPagedPointerGet (operand * left,
7354 sym_link *rtype, *retype;
7356 D(emitcode (";", "genPagedPointerGet"));
7358 rtype = operandType (result);
7359 retype = getSpec (rtype);
7361 aopOp (left, ic, FALSE);
7363 /* if the value is already in a pointer register
7364 then don't need anything more */
7365 if (!AOP_INPREG (AOP (left)))
7367 /* otherwise get a free pointer register */
7369 preg = getFreePtr (ic, &aop, FALSE);
7370 emitcode ("mov", "%s,%s",
7372 aopGet (AOP (left), 0, FALSE, TRUE));
7376 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7378 aopOp (result, ic, FALSE);
7380 /* if bitfield then unpack the bits */
7381 if (IS_BITVAR (retype))
7382 genUnpackBits (result, rname, PPOINTER);
7385 /* we have can just get the values */
7386 int size = AOP_SIZE (result);
7392 emitcode ("movx", "a,@%s", rname);
7393 aopPut (AOP (result), "a", offset);
7398 emitcode ("inc", "%s", rname);
7402 /* now some housekeeping stuff */
7403 if (aop) /* we had to allocate for this iCode */
7405 if (pi) aopPut ( AOP (left), rname, 0);
7406 freeAsmop (NULL, aop, ic, TRUE);
7410 /* we did not allocate which means left
7411 already in a pointer register, then
7412 if size > 0 && this could be used again
7413 we have to point it back to where it
7415 if ((AOP_SIZE (result) > 1 &&
7416 !OP_SYMBOL (left)->remat &&
7417 (OP_SYMBOL (left)->liveTo > ic->seq ||
7421 int size = AOP_SIZE (result) - 1;
7423 emitcode ("dec", "%s", rname);
7428 freeAsmop (left, NULL, ic, TRUE);
7429 freeAsmop (result, NULL, ic, TRUE);
7430 if (pi) pi->generated = 1;
7434 /*-----------------------------------------------------------------*/
7435 /* genFarPointerGet - gget value from far space */
7436 /*-----------------------------------------------------------------*/
7438 genFarPointerGet (operand * left,
7439 operand * result, iCode * ic, iCode * pi)
7442 sym_link *retype = getSpec (operandType (result));
7444 D(emitcode (";", "genFarPointerGet"));
7446 aopOp (left, ic, FALSE);
7448 /* if the operand is already in dptr
7449 then we do nothing else we move the value to dptr */
7450 if (AOP_TYPE (left) != AOP_STR)
7452 /* if this is remateriazable */
7453 if (AOP_TYPE (left) == AOP_IMMD)
7454 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7456 { /* we need to get it byte by byte */
7457 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7458 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7461 /* so dptr know contains the address */
7462 aopOp (result, ic, FALSE);
7464 /* if bit then unpack */
7465 if (IS_BITVAR (retype))
7466 genUnpackBits (result, "dptr", FPOINTER);
7469 size = AOP_SIZE (result);
7474 emitcode ("movx", "a,@dptr");
7475 aopPut (AOP (result), "a", offset++);
7477 emitcode ("inc", "dptr");
7481 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7482 aopPut ( AOP (left), "dpl", 0);
7483 aopPut ( AOP (left), "dph", 1);
7486 freeAsmop (left, NULL, ic, TRUE);
7487 freeAsmop (result, NULL, ic, TRUE);
7490 /*-----------------------------------------------------------------*/
7491 /* genCodePointerGet - gget value from code space */
7492 /*-----------------------------------------------------------------*/
7494 genCodePointerGet (operand * left,
7495 operand * result, iCode * ic, iCode *pi)
7498 sym_link *retype = getSpec (operandType (result));
7500 D(emitcode (";", "genCodePointerGet"));
7502 aopOp (left, ic, FALSE);
7504 /* if the operand is already in dptr
7505 then we do nothing else we move the value to dptr */
7506 if (AOP_TYPE (left) != AOP_STR)
7508 /* if this is remateriazable */
7509 if (AOP_TYPE (left) == AOP_IMMD)
7510 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7512 { /* we need to get it byte by byte */
7513 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7514 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7517 /* so dptr know contains the address */
7518 aopOp (result, ic, FALSE);
7520 /* if bit then unpack */
7521 if (IS_BITVAR (retype))
7522 genUnpackBits (result, "dptr", CPOINTER);
7525 size = AOP_SIZE (result);
7530 emitcode ("clr", "a");
7531 emitcode ("movc", "a,@a+dptr");
7532 aopPut (AOP (result), "a", offset++);
7534 emitcode ("inc", "dptr");
7538 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7539 aopPut ( AOP (left), "dpl", 0);
7540 aopPut ( AOP (left), "dph", 1);
7543 freeAsmop (left, NULL, ic, TRUE);
7544 freeAsmop (result, NULL, ic, TRUE);
7547 /*-----------------------------------------------------------------*/
7548 /* genGenPointerGet - gget value from generic pointer space */
7549 /*-----------------------------------------------------------------*/
7551 genGenPointerGet (operand * left,
7552 operand * result, iCode * ic, iCode *pi)
7555 sym_link *retype = getSpec (operandType (result));
7557 D(emitcode (";", "genGenPointerGet"));
7559 aopOp (left, ic, FALSE);
7561 /* if the operand is already in dptr
7562 then we do nothing else we move the value to dptr */
7563 if (AOP_TYPE (left) != AOP_STR)
7565 /* if this is remateriazable */
7566 if (AOP_TYPE (left) == AOP_IMMD)
7568 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7569 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7570 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7572 emitcode ("mov", "b,#%d", pointerCode (retype));
7575 { /* we need to get it byte by byte */
7576 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7577 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7578 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7581 /* so dptr know contains the address */
7582 aopOp (result, ic, FALSE);
7584 /* if bit then unpack */
7585 if (IS_BITVAR (retype))
7586 genUnpackBits (result, "dptr", GPOINTER);
7589 size = AOP_SIZE (result);
7594 emitcode ("lcall", "__gptrget");
7595 aopPut (AOP (result), "a", offset++);
7597 emitcode ("inc", "dptr");
7601 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7602 aopPut ( AOP (left), "dpl", 0);
7603 aopPut ( AOP (left), "dph", 1);
7604 aopPut ( AOP (left), "b", 2);
7607 freeAsmop (left, NULL, ic, TRUE);
7608 freeAsmop (result, NULL, ic, TRUE);
7611 /*-----------------------------------------------------------------*/
7612 /* genPointerGet - generate code for pointer get */
7613 /*-----------------------------------------------------------------*/
7615 genPointerGet (iCode * ic, iCode *pi)
7617 operand *left, *result;
7618 sym_link *type, *etype;
7621 D(emitcode (";", "genPointerGet"));
7623 left = IC_LEFT (ic);
7624 result = IC_RESULT (ic);
7626 /* depending on the type of pointer we need to
7627 move it to the correct pointer register */
7628 type = operandType (left);
7629 etype = getSpec (type);
7630 /* if left is of type of pointer then it is simple */
7631 if (IS_PTR (type) && !IS_FUNC (type->next))
7632 p_type = DCL_TYPE (type);
7635 /* we have to go by the storage class */
7636 p_type = PTR_TYPE (SPEC_OCLS (etype));
7639 /* special case when cast remat */
7640 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7641 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7642 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7643 type = type = operandType (left);
7644 p_type = DCL_TYPE (type);
7646 /* now that we have the pointer type we assign
7647 the pointer values */
7653 genNearPointerGet (left, result, ic, pi);
7657 genPagedPointerGet (left, result, ic, pi);
7661 genFarPointerGet (left, result, ic, pi);
7665 genCodePointerGet (left, result, ic, pi);
7669 genGenPointerGet (left, result, ic, pi);
7675 /*-----------------------------------------------------------------*/
7676 /* genPackBits - generates code for packed bit storage */
7677 /*-----------------------------------------------------------------*/
7679 genPackBits (sym_link * etype,
7681 char *rname, int p_type)
7689 D(emitcode (";", "genPackBits"));
7691 blen = SPEC_BLEN (etype);
7692 bstr = SPEC_BSTR (etype);
7694 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7697 /* if the bit lenth is less than or */
7698 /* it exactly fits a byte then */
7699 if (SPEC_BLEN (etype) <= 8)
7701 shCount = SPEC_BSTR (etype);
7703 /* shift left acc */
7706 if (SPEC_BLEN (etype) < 8)
7707 { /* if smaller than a byte */
7713 emitcode ("mov", "b,a");
7714 emitcode ("mov", "a,@%s", rname);
7718 emitcode ("mov", "b,a");
7719 emitcode ("movx", "a,@dptr");
7723 emitcode ("push", "b");
7724 emitcode ("push", "acc");
7725 emitcode ("lcall", "__gptrget");
7726 emitcode ("pop", "b");
7730 emitcode ("anl", "a,#0x%02x", (unsigned char)
7731 ((unsigned char) (0xFF << (blen + bstr)) |
7732 (unsigned char) (0xFF >> (8 - bstr))));
7733 emitcode ("orl", "a,b");
7734 if (p_type == GPOINTER)
7735 emitcode ("pop", "b");
7742 emitcode ("mov", "@%s,a", rname);
7746 emitcode ("movx", "@dptr,a");
7750 emitcode ("lcall", "__gptrput");
7755 if (SPEC_BLEN (etype) <= 8)
7758 emitcode ("inc", "%s", rname);
7759 rLen = SPEC_BLEN (etype);
7761 /* now generate for lengths greater than one byte */
7765 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7777 emitcode ("mov", "@%s,a", rname);
7780 emitcode ("mov", "@%s,%s", rname, l);
7785 emitcode ("movx", "@dptr,a");
7790 emitcode ("lcall", "__gptrput");
7793 emitcode ("inc", "%s", rname);
7798 /* last last was not complete */
7801 /* save the byte & read byte */
7805 emitcode ("mov", "b,a");
7806 emitcode ("mov", "a,@%s", rname);
7810 emitcode ("mov", "b,a");
7811 emitcode ("movx", "a,@dptr");
7815 emitcode ("push", "b");
7816 emitcode ("push", "acc");
7817 emitcode ("lcall", "__gptrget");
7818 emitcode ("pop", "b");
7822 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7823 emitcode ("orl", "a,b");
7826 if (p_type == GPOINTER)
7827 emitcode ("pop", "b");
7833 emitcode ("mov", "@%s,a", rname);
7837 emitcode ("movx", "@dptr,a");
7841 emitcode ("lcall", "__gptrput");
7845 /*-----------------------------------------------------------------*/
7846 /* genDataPointerSet - remat pointer to data space */
7847 /*-----------------------------------------------------------------*/
7849 genDataPointerSet (operand * right,
7853 int size, offset = 0;
7854 char *l, buffer[256];
7856 D(emitcode (";", "genDataPointerSet"));
7858 aopOp (right, ic, FALSE);
7860 l = aopGet (AOP (result), 0, FALSE, TRUE);
7861 size = AOP_SIZE (right);
7865 sprintf (buffer, "(%s + %d)", l + 1, offset);
7867 sprintf (buffer, "%s", l + 1);
7868 emitcode ("mov", "%s,%s", buffer,
7869 aopGet (AOP (right), offset++, FALSE, FALSE));
7872 freeAsmop (right, NULL, ic, TRUE);
7873 freeAsmop (result, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genNearPointerSet - emitcode for near pointer put */
7878 /*-----------------------------------------------------------------*/
7880 genNearPointerSet (operand * right,
7888 sym_link *retype, *letype;
7889 sym_link *ptype = operandType (result);
7891 D(emitcode (";", "genNearPointerSet"));
7893 retype = getSpec (operandType (right));
7894 letype = getSpec (ptype);
7895 aopOp (result, ic, FALSE);
7897 /* if the result is rematerializable &
7898 in data space & not a bit variable */
7899 if (AOP_TYPE (result) == AOP_IMMD &&
7900 DCL_TYPE (ptype) == POINTER &&
7901 !IS_BITVAR (retype) &&
7902 !IS_BITVAR (letype))
7904 genDataPointerSet (right, result, ic);
7908 /* if the value is already in a pointer register
7909 then don't need anything more */
7910 if (!AOP_INPREG (AOP (result)))
7913 //AOP_TYPE (result) == AOP_STK
7917 // Aha, it is a pointer, just in disguise.
7918 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7921 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7922 __FILE__, __LINE__);
7927 rname++; // skip the '@'.
7932 /* otherwise get a free pointer register */
7934 preg = getFreePtr (ic, &aop, FALSE);
7935 emitcode ("mov", "%s,%s",
7937 aopGet (AOP (result), 0, FALSE, TRUE));
7943 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7946 aopOp (right, ic, FALSE);
7948 /* if bitfield then unpack the bits */
7949 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7950 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7953 /* we have can just get the values */
7954 int size = AOP_SIZE (right);
7959 l = aopGet (AOP (right), offset, FALSE, TRUE);
7963 emitcode ("mov", "@%s,a", rname);
7966 emitcode ("mov", "@%s,%s", rname, l);
7968 emitcode ("inc", "%s", rname);
7973 /* now some housekeeping stuff */
7974 if (aop) /* we had to allocate for this iCode */
7976 if (pi) aopPut (AOP (result),rname,0);
7977 freeAsmop (NULL, aop, ic, TRUE);
7981 /* we did not allocate which means left
7982 already in a pointer register, then
7983 if size > 0 && this could be used again
7984 we have to point it back to where it
7986 if ((AOP_SIZE (right) > 1 &&
7987 !OP_SYMBOL (result)->remat &&
7988 (OP_SYMBOL (result)->liveTo > ic->seq ||
7992 int size = AOP_SIZE (right) - 1;
7994 emitcode ("dec", "%s", rname);
7999 if (pi) pi->generated = 1;
8000 freeAsmop (result, NULL, ic, TRUE);
8001 freeAsmop (right, NULL, ic, TRUE);
8004 /*-----------------------------------------------------------------*/
8005 /* genPagedPointerSet - emitcode for Paged pointer put */
8006 /*-----------------------------------------------------------------*/
8008 genPagedPointerSet (operand * right,
8016 sym_link *retype, *letype;
8018 D(emitcode (";", "genPagedPointerSet"));
8020 retype = getSpec (operandType (right));
8021 letype = getSpec (operandType (result));
8023 aopOp (result, ic, FALSE);
8025 /* if the value is already in a pointer register
8026 then don't need anything more */
8027 if (!AOP_INPREG (AOP (result)))
8029 /* otherwise get a free pointer register */
8031 preg = getFreePtr (ic, &aop, FALSE);
8032 emitcode ("mov", "%s,%s",
8034 aopGet (AOP (result), 0, FALSE, TRUE));
8038 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8040 aopOp (right, ic, FALSE);
8042 /* if bitfield then unpack the bits */
8043 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8044 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8047 /* we have can just get the values */
8048 int size = AOP_SIZE (right);
8053 l = aopGet (AOP (right), offset, FALSE, TRUE);
8056 emitcode ("movx", "@%s,a", rname);
8059 emitcode ("inc", "%s", rname);
8065 /* now some housekeeping stuff */
8066 if (aop) /* we had to allocate for this iCode */
8068 if (pi) aopPut (AOP (result),rname,0);
8069 freeAsmop (NULL, aop, ic, TRUE);
8073 /* we did not allocate which means left
8074 already in a pointer register, then
8075 if size > 0 && this could be used again
8076 we have to point it back to where it
8078 if (AOP_SIZE (right) > 1 &&
8079 !OP_SYMBOL (result)->remat &&
8080 (OP_SYMBOL (result)->liveTo > ic->seq ||
8083 int size = AOP_SIZE (right) - 1;
8085 emitcode ("dec", "%s", rname);
8090 if (pi) pi->generated = 1;
8091 freeAsmop (result, NULL, ic, TRUE);
8092 freeAsmop (right, NULL, ic, TRUE);
8097 /*-----------------------------------------------------------------*/
8098 /* genFarPointerSet - set value from far space */
8099 /*-----------------------------------------------------------------*/
8101 genFarPointerSet (operand * right,
8102 operand * result, iCode * ic, iCode * pi)
8105 sym_link *retype = getSpec (operandType (right));
8106 sym_link *letype = getSpec (operandType (result));
8108 D(emitcode (";", "genFarPointerSet"));
8110 aopOp (result, ic, FALSE);
8112 /* if the operand is already in dptr
8113 then we do nothing else we move the value to dptr */
8114 if (AOP_TYPE (result) != AOP_STR)
8116 /* if this is remateriazable */
8117 if (AOP_TYPE (result) == AOP_IMMD)
8118 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8120 { /* we need to get it byte by byte */
8121 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8122 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8125 /* so dptr know contains the address */
8126 aopOp (right, ic, FALSE);
8128 /* if bit then unpack */
8129 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8130 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8133 size = AOP_SIZE (right);
8138 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8140 emitcode ("movx", "@dptr,a");
8142 emitcode ("inc", "dptr");
8145 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8146 aopPut (AOP(result),"dpl",0);
8147 aopPut (AOP(result),"dph",1);
8150 freeAsmop (result, NULL, ic, TRUE);
8151 freeAsmop (right, NULL, ic, TRUE);
8154 /*-----------------------------------------------------------------*/
8155 /* genGenPointerSet - set value from generic pointer space */
8156 /*-----------------------------------------------------------------*/
8158 genGenPointerSet (operand * right,
8159 operand * result, iCode * ic, iCode * pi)
8162 sym_link *retype = getSpec (operandType (right));
8163 sym_link *letype = getSpec (operandType (result));
8165 D(emitcode (";", "genGenPointerSet"));
8167 aopOp (result, ic, FALSE);
8169 /* if the operand is already in dptr
8170 then we do nothing else we move the value to dptr */
8171 if (AOP_TYPE (result) != AOP_STR)
8173 /* if this is remateriazable */
8174 if (AOP_TYPE (result) == AOP_IMMD)
8176 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8177 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8178 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8180 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8183 { /* we need to get it byte by byte */
8184 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8185 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8186 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8189 /* so dptr know contains the address */
8190 aopOp (right, ic, FALSE);
8192 /* if bit then unpack */
8193 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8194 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8197 size = AOP_SIZE (right);
8202 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8204 emitcode ("lcall", "__gptrput");
8206 emitcode ("inc", "dptr");
8210 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8211 aopPut (AOP(result),"dpl",0);
8212 aopPut (AOP(result),"dph",1);
8213 aopPut (AOP(result),"b",2);
8216 freeAsmop (result, NULL, ic, TRUE);
8217 freeAsmop (right, NULL, ic, TRUE);
8220 /*-----------------------------------------------------------------*/
8221 /* genPointerSet - stores the value into a pointer location */
8222 /*-----------------------------------------------------------------*/
8224 genPointerSet (iCode * ic, iCode *pi)
8226 operand *right, *result;
8227 sym_link *type, *etype;
8230 D(emitcode (";", "genPointerSet"));
8232 right = IC_RIGHT (ic);
8233 result = IC_RESULT (ic);
8235 /* depending on the type of pointer we need to
8236 move it to the correct pointer register */
8237 type = operandType (result);
8238 etype = getSpec (type);
8239 /* if left is of type of pointer then it is simple */
8240 if (IS_PTR (type) && !IS_FUNC (type->next))
8242 p_type = DCL_TYPE (type);
8246 /* we have to go by the storage class */
8247 p_type = PTR_TYPE (SPEC_OCLS (etype));
8250 /* special case when cast remat */
8251 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8252 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8253 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8254 type = type = operandType (result);
8255 p_type = DCL_TYPE (type);
8257 /* now that we have the pointer type we assign
8258 the pointer values */
8264 genNearPointerSet (right, result, ic, pi);
8268 genPagedPointerSet (right, result, ic, pi);
8272 genFarPointerSet (right, result, ic, pi);
8276 genGenPointerSet (right, result, ic, pi);
8280 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8281 "genPointerSet: illegal pointer type");
8286 /*-----------------------------------------------------------------*/
8287 /* genIfx - generate code for Ifx statement */
8288 /*-----------------------------------------------------------------*/
8290 genIfx (iCode * ic, iCode * popIc)
8292 operand *cond = IC_COND (ic);
8295 D(emitcode (";", "genIfx"));
8297 aopOp (cond, ic, FALSE);
8299 /* get the value into acc */
8300 if (AOP_TYPE (cond) != AOP_CRY)
8304 /* the result is now in the accumulator */
8305 freeAsmop (cond, NULL, ic, TRUE);
8307 /* if there was something to be popped then do it */
8311 /* if the condition is a bit variable */
8312 if (isbit && IS_ITEMP (cond) &&
8314 genIfxJump (ic, SPIL_LOC (cond)->rname);
8315 else if (isbit && !IS_ITEMP (cond))
8316 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8318 genIfxJump (ic, "a");
8323 /*-----------------------------------------------------------------*/
8324 /* genAddrOf - generates code for address of */
8325 /*-----------------------------------------------------------------*/
8327 genAddrOf (iCode * ic)
8329 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8332 D(emitcode (";", "genAddrOf"));
8334 aopOp (IC_RESULT (ic), ic, FALSE);
8336 /* if the operand is on the stack then we
8337 need to get the stack offset of this
8341 /* if it has an offset then we need to compute
8345 emitcode ("mov", "a,_bp");
8346 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8347 ((char) (sym->stack - _G.nRegsSaved)) :
8348 ((char) sym->stack)) & 0xff);
8349 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8353 /* we can just move _bp */
8354 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8356 /* fill the result with zero */
8357 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8362 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8368 /* object not on stack then we need the name */
8369 size = AOP_SIZE (IC_RESULT (ic));
8374 char s[SDCC_NAME_MAX];
8376 sprintf (s, "#(%s >> %d)",
8380 sprintf (s, "#%s", sym->rname);
8381 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8385 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8389 /*-----------------------------------------------------------------*/
8390 /* genFarFarAssign - assignment when both are in far space */
8391 /*-----------------------------------------------------------------*/
8393 genFarFarAssign (operand * result, operand * right, iCode * ic)
8395 int size = AOP_SIZE (right);
8399 D(emitcode (";", "genFarFarAssign"));
8401 /* first push the right side on to the stack */
8404 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8406 emitcode ("push", "acc");
8409 freeAsmop (right, NULL, ic, FALSE);
8410 /* now assign DPTR to result */
8411 aopOp (result, ic, FALSE);
8412 size = AOP_SIZE (result);
8415 emitcode ("pop", "acc");
8416 aopPut (AOP (result), "a", --offset);
8418 freeAsmop (result, NULL, ic, FALSE);
8422 /*-----------------------------------------------------------------*/
8423 /* genAssign - generate code for assignment */
8424 /*-----------------------------------------------------------------*/
8426 genAssign (iCode * ic)
8428 operand *result, *right;
8430 unsigned long lit = 0L;
8432 D(emitcode(";","genAssign"));
8434 result = IC_RESULT (ic);
8435 right = IC_RIGHT (ic);
8437 /* if they are the same */
8438 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8441 aopOp (right, ic, FALSE);
8443 /* special case both in far space */
8444 if (AOP_TYPE (right) == AOP_DPTR &&
8445 IS_TRUE_SYMOP (result) &&
8446 isOperandInFarSpace (result))
8449 genFarFarAssign (result, right, ic);
8453 aopOp (result, ic, TRUE);
8455 /* if they are the same registers */
8456 if (sameRegs (AOP (right), AOP (result)))
8459 /* if the result is a bit */
8460 if (AOP_TYPE (result) == AOP_CRY)
8463 /* if the right size is a literal then
8464 we know what the value is */
8465 if (AOP_TYPE (right) == AOP_LIT)
8467 if (((int) operandLitValue (right)))
8468 aopPut (AOP (result), one, 0);
8470 aopPut (AOP (result), zero, 0);
8474 /* the right is also a bit variable */
8475 if (AOP_TYPE (right) == AOP_CRY)
8477 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8478 aopPut (AOP (result), "c", 0);
8484 aopPut (AOP (result), "a", 0);
8488 /* bit variables done */
8490 size = AOP_SIZE (result);
8492 if (AOP_TYPE (right) == AOP_LIT)
8493 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8495 (AOP_TYPE (result) != AOP_REG) &&
8496 (AOP_TYPE (right) == AOP_LIT) &&
8497 !IS_FLOAT (operandType (right)) &&
8500 emitcode ("clr", "a");
8503 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8504 aopPut (AOP (result), "a", size);
8506 aopPut (AOP (result),
8507 aopGet (AOP (right), size, FALSE, FALSE),
8515 aopPut (AOP (result),
8516 aopGet (AOP (right), offset, FALSE, FALSE),
8523 freeAsmop (right, NULL, ic, TRUE);
8524 freeAsmop (result, NULL, ic, TRUE);
8527 /*-----------------------------------------------------------------*/
8528 /* genJumpTab - genrates code for jump table */
8529 /*-----------------------------------------------------------------*/
8531 genJumpTab (iCode * ic)
8536 D(emitcode (";", "genJumpTab"));
8538 aopOp (IC_JTCOND (ic), ic, FALSE);
8539 /* get the condition into accumulator */
8540 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8542 /* multiply by three */
8543 emitcode ("add", "a,acc");
8544 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8545 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8547 jtab = newiTempLabel (NULL);
8548 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8549 emitcode ("jmp", "@a+dptr");
8550 emitcode ("", "%05d$:", jtab->key + 100);
8551 /* now generate the jump labels */
8552 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8553 jtab = setNextItem (IC_JTLABELS (ic)))
8554 emitcode ("ljmp", "%05d$", jtab->key + 100);
8558 /*-----------------------------------------------------------------*/
8559 /* genCast - gen code for casting */
8560 /*-----------------------------------------------------------------*/
8562 genCast (iCode * ic)
8564 operand *result = IC_RESULT (ic);
8565 sym_link *ctype = operandType (IC_LEFT (ic));
8566 sym_link *rtype = operandType (IC_RIGHT (ic));
8567 operand *right = IC_RIGHT (ic);
8570 D(emitcode(";", "genCast"));
8572 /* if they are equivalent then do nothing */
8573 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8576 aopOp (right, ic, FALSE);
8577 aopOp (result, ic, FALSE);
8579 /* if the result is a bit */
8580 if (IS_BITVAR(OP_SYMBOL(result)->type))
8582 /* if the right size is a literal then
8583 we know what the value is */
8584 if (AOP_TYPE (right) == AOP_LIT)
8586 if (((int) operandLitValue (right)))
8587 aopPut (AOP (result), one, 0);
8589 aopPut (AOP (result), zero, 0);
8594 /* the right is also a bit variable */
8595 if (AOP_TYPE (right) == AOP_CRY)
8597 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8598 aopPut (AOP (result), "c", 0);
8604 aopPut (AOP (result), "a", 0);
8608 /* if they are the same size : or less */
8609 if (AOP_SIZE (result) <= AOP_SIZE (right))
8612 /* if they are in the same place */
8613 if (sameRegs (AOP (right), AOP (result)))
8616 /* if they in different places then copy */
8617 size = AOP_SIZE (result);
8621 aopPut (AOP (result),
8622 aopGet (AOP (right), offset, FALSE, FALSE),
8630 /* if the result is of type pointer */
8635 sym_link *type = operandType (right);
8636 sym_link *etype = getSpec (type);
8638 /* pointer to generic pointer */
8639 if (IS_GENPTR (ctype))
8642 p_type = DCL_TYPE (type);
8645 if (SPEC_SCLS(etype)==S_REGISTER) {
8646 // let's assume it is a generic pointer
8649 /* we have to go by the storage class */
8650 p_type = PTR_TYPE (SPEC_OCLS (etype));
8654 /* the first two bytes are known */
8655 size = GPTRSIZE - 1;
8659 aopPut (AOP (result),
8660 aopGet (AOP (right), offset, FALSE, FALSE),
8664 /* the last byte depending on type */
8666 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8671 // pointerTypeToGPByte will have bitched.
8675 sprintf(gpValStr, "#0x%d", gpVal);
8676 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8681 /* just copy the pointers */
8682 size = AOP_SIZE (result);
8686 aopPut (AOP (result),
8687 aopGet (AOP (right), offset, FALSE, FALSE),
8694 /* so we now know that the size of destination is greater
8695 than the size of the source */
8696 /* we move to result for the size of source */
8697 size = AOP_SIZE (right);
8701 aopPut (AOP (result),
8702 aopGet (AOP (right), offset, FALSE, FALSE),
8707 /* now depending on the sign of the source && destination */
8708 size = AOP_SIZE (result) - AOP_SIZE (right);
8709 /* if unsigned or not an integral type */
8710 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8713 aopPut (AOP (result), zero, offset++);
8717 /* we need to extend the sign :{ */
8718 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8721 emitcode ("rlc", "a");
8722 emitcode ("subb", "a,acc");
8724 aopPut (AOP (result), "a", offset++);
8727 /* we are done hurray !!!! */
8730 freeAsmop (right, NULL, ic, TRUE);
8731 freeAsmop (result, NULL, ic, TRUE);
8735 /*-----------------------------------------------------------------*/
8736 /* genDjnz - generate decrement & jump if not zero instrucion */
8737 /*-----------------------------------------------------------------*/
8739 genDjnz (iCode * ic, iCode * ifx)
8745 D(emitcode (";", "genDjnz"));
8747 /* if the if condition has a false label
8748 then we cannot save */
8752 /* if the minus is not of the form
8754 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8755 !IS_OP_LITERAL (IC_RIGHT (ic)))
8758 if (operandLitValue (IC_RIGHT (ic)) != 1)
8761 /* if the size of this greater than one then no
8763 if (getSize (operandType (IC_RESULT (ic))) > 1)
8766 /* otherwise we can save BIG */
8767 lbl = newiTempLabel (NULL);
8768 lbl1 = newiTempLabel (NULL);
8770 aopOp (IC_RESULT (ic), ic, FALSE);
8772 if (AOP_NEEDSACC(IC_RESULT(ic)))
8774 /* If the result is accessed indirectly via
8775 * the accumulator, we must explicitly write
8776 * it back after the decrement.
8778 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8780 if (strcmp(rByte, "a"))
8782 /* Something is hopelessly wrong */
8783 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8784 __FILE__, __LINE__);
8785 /* We can just give up; the generated code will be inefficient,
8788 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8791 emitcode ("dec", "%s", rByte);
8792 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8793 emitcode ("jnz", "%05d$", lbl->key + 100);
8795 else if (IS_AOP_PREG (IC_RESULT (ic)))
8797 emitcode ("dec", "%s",
8798 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8799 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8800 emitcode ("jnz", "%05d$", lbl->key + 100);
8804 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8807 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8808 emitcode ("", "%05d$:", lbl->key + 100);
8809 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8810 emitcode ("", "%05d$:", lbl1->key + 100);
8812 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8817 /*-----------------------------------------------------------------*/
8818 /* genReceive - generate code for a receive iCode */
8819 /*-----------------------------------------------------------------*/
8821 genReceive (iCode * ic)
8823 int size = getSize (operandType (IC_RESULT (ic)));
8825 D(emitcode (";", "genReceive"));
8827 if (ic->argreg == 1) { /* first parameter */
8828 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8829 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8830 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8832 offset = fReturnSizeMCS51 - size;
8834 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8835 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8838 aopOp (IC_RESULT (ic), ic, FALSE);
8839 size = AOP_SIZE (IC_RESULT (ic));
8842 emitcode ("pop", "acc");
8843 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8848 aopOp (IC_RESULT (ic), ic, FALSE);
8850 assignResultValue (IC_RESULT (ic));
8852 } else { /* second receive onwards */
8854 aopOp (IC_RESULT (ic), ic, FALSE);
8855 rb1off = ic->argreg;
8857 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8860 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8863 /*-----------------------------------------------------------------*/
8864 /* gen51Code - generate code for 8051 based controllers */
8865 /*-----------------------------------------------------------------*/
8867 gen51Code (iCode * lic)
8872 lineHead = lineCurr = NULL;
8874 /* print the allocation information */
8876 printAllocInfo (currFunc, codeOutFile);
8877 /* if debug information required */
8878 if (options.debug && currFunc)
8880 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8882 if (IS_STATIC (currFunc->etype))
8883 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8885 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8888 /* stack pointer name */
8889 if (options.useXstack)
8895 for (ic = lic; ic; ic = ic->next)
8898 if (ic->lineno && cln != ic->lineno)
8903 emitcode ("", "C$%s$%d$%d$%d ==.",
8904 FileBaseName (ic->filename), ic->lineno,
8905 ic->level, ic->block);
8908 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
8909 printCLine(ic->filename, ic->lineno));
8912 /* if the result is marked as
8913 spilt and rematerializable or code for
8914 this has already been generated then
8916 if (resultRemat (ic) || ic->generated)
8919 /* depending on the operation */
8939 /* IPOP happens only when trying to restore a
8940 spilt live range, if there is an ifx statement
8941 following this pop then the if statement might
8942 be using some of the registers being popped which
8943 would destory the contents of the register so
8944 we need to check for this condition and handle it */
8946 ic->next->op == IFX &&
8947 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8948 genIfx (ic->next, ic);
8966 genEndFunction (ic);
8986 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9003 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9007 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9014 /* note these two are xlated by algebraic equivalence
9015 during parsing SDCC.y */
9016 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9017 "got '>=' or '<=' shouldn't have come here");
9021 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9033 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9037 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9041 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9068 case GET_VALUE_AT_ADDRESS:
9069 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9073 if (POINTER_SET (ic))
9074 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9100 addSet (&_G.sendSet, ic);
9109 /* now we are ready to call the
9110 peep hole optimizer */
9111 if (!options.nopeep)
9112 peepHole (&lineHead);
9114 /* now do the actual printing */
9115 printLine (lineHead, codeOutFile);