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))
796 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
805 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
809 /* Error case --- will have been caught already */
816 /*-----------------------------------------------------------------*/
817 /* aopGet - for fetching value of the aop */
818 /*-----------------------------------------------------------------*/
820 aopGet (asmop * aop, int offset, bool bit16, bool dname)
825 /* offset is greater than
827 if (offset > (aop->size - 1) &&
828 aop->type != AOP_LIT)
831 /* depending on type */
837 /* if we need to increment it */
838 while (offset > aop->coff)
840 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
844 while (offset < aop->coff)
846 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
853 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
854 return (dname ? "acc" : "a");
856 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
857 rs = Safe_calloc (1, strlen (s) + 1);
862 if (aop->code && aop->coff==0 && offset>=1) {
863 emitcode ("mov", "a,#0x%02x", offset);
864 emitcode ("movc", "a,@a+dptr");
865 return (dname ? "acc" : "a");
868 while (offset > aop->coff)
870 emitcode ("inc", "dptr");
874 while (offset < aop->coff)
876 emitcode ("lcall", "__decdptr");
883 emitcode ("clr", "a");
884 emitcode ("movc", "a,@a+dptr");
888 emitcode ("movx", "a,@dptr");
890 return (dname ? "acc" : "a");
894 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
895 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
897 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
899 sprintf (s, "#(%s >> %d)",
900 aop->aopu.aop_immd.aop_immd1,
904 aop->aopu.aop_immd.aop_immd1);
905 rs = Safe_calloc (1, strlen (s) + 1);
911 sprintf (s, "(%s + %d)",
915 sprintf (s, "%s", aop->aopu.aop_dir);
916 rs = Safe_calloc (1, strlen (s) + 1);
922 return aop->aopu.aop_reg[offset]->dname;
924 return aop->aopu.aop_reg[offset]->name;
927 emitcode ("clr", "a");
928 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
929 emitcode ("rlc", "a");
930 return (dname ? "acc" : "a");
933 if (!offset && dname)
935 return aop->aopu.aop_str[offset];
938 return aopLiteral (aop->aopu.aop_lit, offset);
942 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
946 return aop->aopu.aop_str[offset];
950 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
951 "aopget got unsupported aop->type");
954 /*-----------------------------------------------------------------*/
955 /* aopPut - puts a string for a aop */
956 /*-----------------------------------------------------------------*/
958 aopPut (asmop * aop, char *s, int offset)
962 if (aop->size && offset > (aop->size - 1))
964 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
965 "aopPut got offset > aop->size");
969 /* will assign value to value */
970 /* depending on where it is ofcourse */
975 sprintf (d, "(%s + %d)",
976 aop->aopu.aop_dir, offset);
978 sprintf (d, "%s", aop->aopu.aop_dir);
981 emitcode ("mov", "%s,%s", d, s);
986 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
987 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
990 strcmp (s, "r0") == 0 ||
991 strcmp (s, "r1") == 0 ||
992 strcmp (s, "r2") == 0 ||
993 strcmp (s, "r3") == 0 ||
994 strcmp (s, "r4") == 0 ||
995 strcmp (s, "r5") == 0 ||
996 strcmp (s, "r6") == 0 ||
997 strcmp (s, "r7") == 0)
998 emitcode ("mov", "%s,%s",
999 aop->aopu.aop_reg[offset]->dname, s);
1001 emitcode ("mov", "%s,%s",
1002 aop->aopu.aop_reg[offset]->name, s);
1009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1010 "aopPut writting to code space");
1014 while (offset > aop->coff)
1017 emitcode ("inc", "dptr");
1020 while (offset < aop->coff)
1023 emitcode ("lcall", "__decdptr");
1028 /* if not in accumulater */
1031 emitcode ("movx", "@dptr,a");
1036 while (offset > aop->coff)
1039 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1041 while (offset < aop->coff)
1044 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1051 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1057 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1059 else if (strcmp (s, "r0") == 0 ||
1060 strcmp (s, "r1") == 0 ||
1061 strcmp (s, "r2") == 0 ||
1062 strcmp (s, "r3") == 0 ||
1063 strcmp (s, "r4") == 0 ||
1064 strcmp (s, "r5") == 0 ||
1065 strcmp (s, "r6") == 0 ||
1066 strcmp (s, "r7") == 0)
1069 sprintf (buffer, "a%s", s);
1070 emitcode ("mov", "@%s,%s",
1071 aop->aopu.aop_ptr->name, buffer);
1074 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1079 if (strcmp (s, "a") == 0)
1080 emitcode ("push", "acc");
1084 emitcode ("push", "acc");
1086 emitcode ("push", s);
1092 /* if bit variable */
1093 if (!aop->aopu.aop_dir)
1095 emitcode ("clr", "a");
1096 emitcode ("rlc", "a");
1101 emitcode ("clr", "%s", aop->aopu.aop_dir);
1103 emitcode ("setb", "%s", aop->aopu.aop_dir);
1104 else if (!strcmp (s, "c"))
1105 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1108 if (strcmp (s, "a"))
1113 /* set C, if a >= 1 */
1114 emitcode ("add", "a,#0xff");
1115 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1123 if (strcmp (aop->aopu.aop_str[offset], s))
1124 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1129 if (!offset && (strcmp (s, "acc") == 0))
1132 if (strcmp (aop->aopu.aop_str[offset], s))
1133 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1137 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1138 "aopPut got unsupported aop->type");
1146 /*-----------------------------------------------------------------*/
1147 /* pointToEnd :- points to the last byte of the operand */
1148 /*-----------------------------------------------------------------*/
1150 pointToEnd (asmop * aop)
1156 aop->coff = count = (aop->size - 1);
1162 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1166 emitcode ("inc", "dptr");
1173 /*-----------------------------------------------------------------*/
1174 /* reAdjustPreg - points a register back to where it should */
1175 /*-----------------------------------------------------------------*/
1177 reAdjustPreg (asmop * aop)
1179 if ((aop->coff==0) || aop->size <= 1)
1187 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1192 emitcode ("lcall", "__decdptr");
1199 #define AOP(op) op->aop
1200 #define AOP_TYPE(op) AOP(op)->type
1201 #define AOP_SIZE(op) AOP(op)->size
1202 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1203 AOP_TYPE(x) == AOP_R0))
1205 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1206 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1208 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1209 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1210 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1212 /*-----------------------------------------------------------------*/
1213 /* genNotFloat - generates not for float operations */
1214 /*-----------------------------------------------------------------*/
1216 genNotFloat (operand * op, operand * res)
1222 D(emitcode ("; genNotFloat",""));
1224 /* we will put 127 in the first byte of
1226 aopPut (AOP (res), "#127", 0);
1227 size = AOP_SIZE (op) - 1;
1230 l = aopGet (op->aop, offset++, FALSE, FALSE);
1235 emitcode ("orl", "a,%s",
1237 offset++, FALSE, FALSE));
1240 tlbl = newiTempLabel (NULL);
1241 aopPut (res->aop, one, 1);
1242 emitcode ("jz", "%05d$", (tlbl->key + 100));
1243 aopPut (res->aop, zero, 1);
1244 emitcode ("", "%05d$:", (tlbl->key + 100));
1246 size = res->aop->size - 2;
1248 /* put zeros in the rest */
1250 aopPut (res->aop, zero, offset++);
1253 /*-----------------------------------------------------------------*/
1254 /* opIsGptr: returns non-zero if the passed operand is */
1255 /* a generic pointer type. */
1256 /*-----------------------------------------------------------------*/
1258 opIsGptr (operand * op)
1260 sym_link *type = operandType (op);
1262 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1269 /*-----------------------------------------------------------------*/
1270 /* getDataSize - get the operand data size */
1271 /*-----------------------------------------------------------------*/
1273 getDataSize (operand * op)
1276 size = AOP_SIZE (op);
1277 if (size == GPTRSIZE)
1279 sym_link *type = operandType (op);
1280 if (IS_GENPTR (type))
1282 /* generic pointer; arithmetic operations
1283 * should ignore the high byte (pointer type).
1291 /*-----------------------------------------------------------------*/
1292 /* outAcc - output Acc */
1293 /*-----------------------------------------------------------------*/
1295 outAcc (operand * result)
1298 size = getDataSize (result);
1301 aopPut (AOP (result), "a", 0);
1304 /* unsigned or positive */
1307 aopPut (AOP (result), zero, offset++);
1312 /*-----------------------------------------------------------------*/
1313 /* outBitC - output a bit C */
1314 /*-----------------------------------------------------------------*/
1316 outBitC (operand * result)
1318 /* if the result is bit */
1319 if (AOP_TYPE (result) == AOP_CRY)
1320 aopPut (AOP (result), "c", 0);
1323 emitcode ("clr", "a");
1324 emitcode ("rlc", "a");
1329 /*-----------------------------------------------------------------*/
1330 /* toBoolean - emit code for orl a,operator(sizeop) */
1331 /*-----------------------------------------------------------------*/
1333 toBoolean (operand * oper)
1335 int size = AOP_SIZE (oper) - 1;
1337 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1339 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1343 /*-----------------------------------------------------------------*/
1344 /* genNot - generate code for ! operation */
1345 /*-----------------------------------------------------------------*/
1350 sym_link *optype = operandType (IC_LEFT (ic));
1352 D(emitcode ("; genNot",""));
1354 /* assign asmOps to operand & result */
1355 aopOp (IC_LEFT (ic), ic, FALSE);
1356 aopOp (IC_RESULT (ic), ic, TRUE);
1358 /* if in bit space then a special case */
1359 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1361 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1362 emitcode ("cpl", "c");
1363 outBitC (IC_RESULT (ic));
1367 /* if type float then do float */
1368 if (IS_FLOAT (optype))
1370 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1374 toBoolean (IC_LEFT (ic));
1376 tlbl = newiTempLabel (NULL);
1377 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1378 emitcode ("", "%05d$:", tlbl->key + 100);
1379 outBitC (IC_RESULT (ic));
1382 /* release the aops */
1383 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1384 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1388 /*-----------------------------------------------------------------*/
1389 /* genCpl - generate code for complement */
1390 /*-----------------------------------------------------------------*/
1398 D(emitcode ("; genCpl",""));
1400 /* assign asmOps to operand & result */
1401 aopOp (IC_LEFT (ic), ic, FALSE);
1402 aopOp (IC_RESULT (ic), ic, TRUE);
1404 /* special case if in bit space */
1405 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1406 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1407 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1408 emitcode ("cpl", "c");
1409 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1412 tlbl=newiTempLabel(NULL);
1413 emitcode ("cjne", "%s,#0x01,%05d$",
1414 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1415 emitcode ("", "%05d$:", tlbl->key+100);
1416 outBitC (IC_RESULT(ic));
1420 size = AOP_SIZE (IC_RESULT (ic));
1423 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1425 emitcode ("cpl", "a");
1426 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1431 /* release the aops */
1432 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* genUminusFloat - unary minus for floating points */
1438 /*-----------------------------------------------------------------*/
1440 genUminusFloat (operand * op, operand * result)
1442 int size, offset = 0;
1445 D(emitcode ("; genUminusFloat",""));
1447 /* for this we just copy and then flip the bit */
1449 size = AOP_SIZE (op) - 1;
1453 aopPut (AOP (result),
1454 aopGet (AOP (op), offset, FALSE, FALSE),
1459 l = aopGet (AOP (op), offset, FALSE, FALSE);
1463 emitcode ("cpl", "acc.7");
1464 aopPut (AOP (result), "a", offset);
1467 /*-----------------------------------------------------------------*/
1468 /* genUminus - unary minus code generation */
1469 /*-----------------------------------------------------------------*/
1471 genUminus (iCode * ic)
1474 sym_link *optype, *rtype;
1477 D(emitcode ("; genUminus",""));
1480 aopOp (IC_LEFT (ic), ic, FALSE);
1481 aopOp (IC_RESULT (ic), ic, TRUE);
1483 /* if both in bit space then special
1485 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1486 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1489 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1490 emitcode ("cpl", "c");
1491 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1495 optype = operandType (IC_LEFT (ic));
1496 rtype = operandType (IC_RESULT (ic));
1498 /* if float then do float stuff */
1499 if (IS_FLOAT (optype))
1501 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1505 /* otherwise subtract from zero */
1506 size = AOP_SIZE (IC_LEFT (ic));
1511 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1512 if (!strcmp (l, "a"))
1516 emitcode ("cpl", "a");
1517 emitcode ("addc", "a,#0");
1523 emitcode ("clr", "a");
1524 emitcode ("subb", "a,%s", l);
1526 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1529 /* if any remaining bytes in the result */
1530 /* we just need to propagate the sign */
1531 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1533 emitcode ("rlc", "a");
1534 emitcode ("subb", "a,acc");
1536 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1540 /* release the aops */
1541 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* saveRegisters - will look for a call and save the registers */
1547 /*-----------------------------------------------------------------*/
1549 saveRegisters (iCode * lic)
1556 for (ic = lic; ic; ic = ic->next)
1557 if (ic->op == CALL || ic->op == PCALL)
1562 fprintf (stderr, "found parameter push with no function call\n");
1566 /* if the registers have been saved already or don't need to be then
1568 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1569 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1572 /* safe the registers in use at this time but skip the
1573 ones for the result */
1574 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1575 mcs51_rUmaskForOp (IC_RESULT(ic)));
1578 if (options.useXstack)
1580 if (bitVectBitValue (rsave, R0_IDX))
1581 emitcode ("mov", "b,r0");
1582 emitcode ("mov", "r0,%s", spname);
1583 for (i = 0; i < mcs51_nRegs; i++)
1585 if (bitVectBitValue (rsave, i))
1588 emitcode ("mov", "a,b");
1590 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1591 emitcode ("movx", "@r0,a");
1592 emitcode ("inc", "r0");
1595 emitcode ("mov", "%s,r0", spname);
1596 if (bitVectBitValue (rsave, R0_IDX))
1597 emitcode ("mov", "r0,b");
1600 for (i = 0; i < mcs51_nRegs; i++)
1602 if (bitVectBitValue (rsave, i))
1603 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1607 /*-----------------------------------------------------------------*/
1608 /* unsaveRegisters - pop the pushed registers */
1609 /*-----------------------------------------------------------------*/
1611 unsaveRegisters (iCode * ic)
1616 /* restore the registers in use at this time but skip the
1617 ones for the result */
1618 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1619 mcs51_rUmaskForOp (IC_RESULT(ic)));
1621 if (options.useXstack)
1623 emitcode ("mov", "r0,%s", spname);
1624 for (i = mcs51_nRegs; i >= 0; i--)
1626 if (bitVectBitValue (rsave, i))
1628 emitcode ("dec", "r0");
1629 emitcode ("movx", "a,@r0");
1631 emitcode ("mov", "b,a");
1633 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1637 emitcode ("mov", "%s,r0", spname);
1638 if (bitVectBitValue (rsave, R0_IDX))
1639 emitcode ("mov", "r0,b");
1642 for (i = mcs51_nRegs; i >= 0; i--)
1644 if (bitVectBitValue (rsave, i))
1645 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1651 /*-----------------------------------------------------------------*/
1653 /*-----------------------------------------------------------------*/
1655 pushSide (operand * oper, int size)
1660 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1661 if (AOP_TYPE (oper) != AOP_REG &&
1662 AOP_TYPE (oper) != AOP_DIR &&
1665 emitcode ("mov", "a,%s", l);
1666 emitcode ("push", "acc");
1669 emitcode ("push", "%s", l);
1673 /*-----------------------------------------------------------------*/
1674 /* assignResultValue - */
1675 /*-----------------------------------------------------------------*/
1677 assignResultValue (operand * oper)
1680 int size = AOP_SIZE (oper);
1683 aopPut (AOP (oper), fReturn[offset], offset);
1689 /*-----------------------------------------------------------------*/
1690 /* genXpush - pushes onto the external stack */
1691 /*-----------------------------------------------------------------*/
1693 genXpush (iCode * ic)
1695 asmop *aop = newAsmop (0);
1697 int size, offset = 0;
1699 D(emitcode ("; genXpush",""));
1701 aopOp (IC_LEFT (ic), ic, FALSE);
1702 r = getFreePtr (ic, &aop, FALSE);
1705 emitcode ("mov", "%s,_spx", r->name);
1707 size = AOP_SIZE (IC_LEFT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)),
1712 offset++, FALSE, FALSE);
1714 emitcode ("movx", "@%s,a", r->name);
1715 emitcode ("inc", "%s", r->name);
1720 emitcode ("mov", "_spx,%s", r->name);
1722 freeAsmop (NULL, aop, ic, TRUE);
1723 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* genIpush - genrate code for pushing this gets a little complex */
1728 /*-----------------------------------------------------------------*/
1730 genIpush (iCode * ic)
1732 int size, offset = 0;
1735 D(emitcode ("; genIpush",""));
1737 /* if this is not a parm push : ie. it is spill push
1738 and spill push is always done on the local stack */
1742 /* and the item is spilt then do nothing */
1743 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1746 aopOp (IC_LEFT (ic), ic, FALSE);
1747 size = AOP_SIZE (IC_LEFT (ic));
1748 /* push it on the stack */
1751 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1757 emitcode ("push", "%s", l);
1762 /* this is a paramter push: in this case we call
1763 the routine to find the call and save those
1764 registers that need to be saved */
1767 /* if use external stack then call the external
1768 stack pushing routine */
1769 if (options.useXstack)
1775 /* then do the push */
1776 aopOp (IC_LEFT (ic), ic, FALSE);
1779 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1780 size = AOP_SIZE (IC_LEFT (ic));
1784 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1785 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1786 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1789 emitcode ("mov", "a,%s", l);
1790 emitcode ("push", "acc");
1793 emitcode ("push", "%s", l);
1796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1799 /*-----------------------------------------------------------------*/
1800 /* genIpop - recover the registers: can happen only for spilling */
1801 /*-----------------------------------------------------------------*/
1803 genIpop (iCode * ic)
1807 D(emitcode ("; genIpop",""));
1809 /* if the temp was not pushed then */
1810 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1813 aopOp (IC_LEFT (ic), ic, FALSE);
1814 size = AOP_SIZE (IC_LEFT (ic));
1815 offset = (size - 1);
1817 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1820 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1823 /*-----------------------------------------------------------------*/
1824 /* unsaveRBank - restores the resgister bank from stack */
1825 /*-----------------------------------------------------------------*/
1827 unsaveRBank (int bank, iCode * ic, bool popPsw)
1833 if (options.useXstack)
1837 /* Assume r0 is available for use. */
1838 r = mcs51_regWithIdx (R0_IDX);;
1843 r = getFreePtr (ic, &aop, FALSE);
1845 emitcode ("mov", "%s,_spx", r->name);
1850 if (options.useXstack)
1852 emitcode ("movx", "a,@%s", r->name);
1853 emitcode ("mov", "psw,a");
1854 emitcode ("dec", "%s", r->name);
1858 emitcode ("pop", "psw");
1862 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1864 if (options.useXstack)
1866 emitcode ("movx", "a,@%s", r->name);
1867 emitcode ("mov", "(%s+%d),a",
1868 regs8051[i].base, 8 * bank + regs8051[i].offset);
1869 emitcode ("dec", "%s", r->name);
1873 emitcode ("pop", "(%s+%d)",
1874 regs8051[i].base, 8 * bank + regs8051[i].offset);
1877 if (options.useXstack)
1879 emitcode ("mov", "_spx,%s", r->name);
1884 freeAsmop (NULL, aop, ic, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* saveRBank - saves an entire register bank on the stack */
1890 /*-----------------------------------------------------------------*/
1892 saveRBank (int bank, iCode * ic, bool pushPsw)
1898 if (options.useXstack)
1902 /* Assume r0 is available for use. */
1903 r = mcs51_regWithIdx (R0_IDX);;
1908 r = getFreePtr (ic, &aop, FALSE);
1910 emitcode ("mov", "%s,_spx", r->name);
1913 for (i = 0; i < mcs51_nRegs; i++)
1915 if (options.useXstack)
1917 emitcode ("inc", "%s", r->name);
1918 emitcode ("mov", "a,(%s+%d)",
1919 regs8051[i].base, 8 * bank + regs8051[i].offset);
1920 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("push", "(%s+%d)",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1929 if (options.useXstack)
1931 emitcode ("mov", "a,psw");
1932 emitcode ("movx", "@%s,a", r->name);
1933 emitcode ("inc", "%s", r->name);
1934 emitcode ("mov", "_spx,%s", r->name);
1939 emitcode ("push", "psw");
1942 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1947 freeAsmop (NULL, aop, ic, TRUE);
1956 /*-----------------------------------------------------------------*/
1957 /* genSend - gen code for SEND */
1958 /*-----------------------------------------------------------------*/
1959 static void genSend(set *sendSet)
1964 for (sic = setFirstItem (_G.sendSet); sic;
1965 sic = setNextItem (_G.sendSet)) {
1966 int size, offset = 0;
1967 aopOp (IC_LEFT (sic), sic, FALSE);
1968 size = AOP_SIZE (IC_LEFT (sic));
1970 if (sic->argreg == 1) {
1972 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1974 if (strcmp (l, fReturn[offset]))
1975 emitcode ("mov", "%s,%s", fReturn[offset], l);
1981 emitcode ("mov","b1_%d,%s",rb1_count++,
1982 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1985 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1989 /*-----------------------------------------------------------------*/
1990 /* genCall - generates a call statement */
1991 /*-----------------------------------------------------------------*/
1993 genCall (iCode * ic)
1996 // bool restoreBank = FALSE;
1997 bool swapBanks = FALSE;
1999 D(emitcode("; genCall",""));
2001 dtype = operandType (IC_LEFT (ic));
2002 /* if send set is not empty the assign */
2005 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2006 genSend(reverseSet(_G.sendSet));
2008 genSend(_G.sendSet);
2014 /* if we are calling a not _naked function that is not using
2015 the same register bank then we need to save the
2016 destination registers on the stack */
2017 dtype = operandType (IC_LEFT (ic));
2018 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2019 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2020 !IFFUNC_ISISR (dtype))
2025 /* if caller saves & we have not saved then */
2031 emitcode ("mov", "psw,#0x%02x",
2032 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2036 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2037 OP_SYMBOL (IC_LEFT (ic))->rname :
2038 OP_SYMBOL (IC_LEFT (ic))->name));
2042 emitcode ("mov", "psw,#0x%02x",
2043 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2046 /* if we need assign a result value */
2047 if ((IS_ITEMP (IC_RESULT (ic)) &&
2048 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2049 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2050 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2051 IS_TRUE_SYMOP (IC_RESULT (ic)))
2055 aopOp (IC_RESULT (ic), ic, FALSE);
2058 assignResultValue (IC_RESULT (ic));
2060 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2063 /* adjust the stack for parameters if
2068 if (ic->parmBytes > 3)
2070 emitcode ("mov", "a,%s", spname);
2071 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2072 emitcode ("mov", "%s,a", spname);
2075 for (i = 0; i < ic->parmBytes; i++)
2076 emitcode ("dec", "%s", spname);
2079 /* if we hade saved some registers then unsave them */
2080 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2081 unsaveRegisters (ic);
2083 // /* if register bank was saved then pop them */
2085 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2088 /*-----------------------------------------------------------------*/
2089 /* -10l - generates a call by pointer statement */
2090 /*-----------------------------------------------------------------*/
2092 genPcall (iCode * ic)
2095 symbol *rlbl = newiTempLabel (NULL);
2096 // bool restoreBank=FALSE;
2097 bool swapBanks = FALSE;
2099 D(emitcode("; genPCall",""));
2101 /* if caller saves & we have not saved then */
2105 /* if we are calling a not _naked function that is not using
2106 the same register bank then we need to save the
2107 destination registers on the stack */
2108 dtype = operandType (IC_LEFT (ic))->next;
2109 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2110 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2111 !IFFUNC_ISISR (dtype))
2113 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2114 // restoreBank=TRUE;
2116 // need caution message to user here
2119 /* push the return address on to the stack */
2120 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2121 emitcode ("push", "acc");
2122 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2123 emitcode ("push", "acc");
2125 /* now push the calling address */
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2128 pushSide (IC_LEFT (ic), FPTRSIZE);
2130 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2132 /* if send set is not empty the assign */
2135 genSend(reverseSet(_G.sendSet));
2141 emitcode ("mov", "psw,#0x%02x",
2142 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2146 emitcode ("ret", "");
2147 emitcode ("", "%05d$:", (rlbl->key + 100));
2152 emitcode ("mov", "psw,#0x%02x",
2153 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2156 /* if we need assign a result value */
2157 if ((IS_ITEMP (IC_RESULT (ic)) &&
2158 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2159 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2160 IS_TRUE_SYMOP (IC_RESULT (ic)))
2164 aopOp (IC_RESULT (ic), ic, FALSE);
2167 assignResultValue (IC_RESULT (ic));
2169 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2172 /* adjust the stack for parameters if
2177 if (ic->parmBytes > 3)
2179 emitcode ("mov", "a,%s", spname);
2180 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2181 emitcode ("mov", "%s,a", spname);
2184 for (i = 0; i < ic->parmBytes; i++)
2185 emitcode ("dec", "%s", spname);
2189 // /* if register bank was saved then unsave them */
2191 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2193 /* if we hade saved some registers then
2195 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2196 unsaveRegisters (ic);
2199 /*-----------------------------------------------------------------*/
2200 /* resultRemat - result is rematerializable */
2201 /*-----------------------------------------------------------------*/
2203 resultRemat (iCode * ic)
2205 if (SKIP_IC (ic) || ic->op == IFX)
2208 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2210 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2211 if (sym->remat && !POINTER_SET (ic))
2218 #if defined(__BORLANDC__) || defined(_MSC_VER)
2219 #define STRCASECMP stricmp
2221 #define STRCASECMP strcasecmp
2224 /*-----------------------------------------------------------------*/
2225 /* inExcludeList - return 1 if the string is in exclude Reg list */
2226 /*-----------------------------------------------------------------*/
2228 inExcludeList (char *s)
2232 if (options.excludeRegs[i] &&
2233 STRCASECMP (options.excludeRegs[i], "none") == 0)
2236 for (i = 0; options.excludeRegs[i]; i++)
2238 if (options.excludeRegs[i] &&
2239 STRCASECMP (s, options.excludeRegs[i]) == 0)
2245 /*-----------------------------------------------------------------*/
2246 /* genFunction - generated code for function entry */
2247 /*-----------------------------------------------------------------*/
2249 genFunction (iCode * ic)
2253 bool switchedPSW = FALSE;
2254 int calleesaves_saved_register = -1;
2257 /* create the function header */
2258 emitcode (";", "-----------------------------------------");
2259 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2260 emitcode (";", "-----------------------------------------");
2262 emitcode ("", "%s:", sym->rname);
2263 ftype = operandType (IC_LEFT (ic));
2265 if (IFFUNC_ISNAKED(ftype))
2267 emitcode(";", "naked function: no prologue.");
2271 /* if critical function then turn interrupts off */
2272 if (IFFUNC_ISCRITICAL (ftype))
2273 emitcode ("clr", "ea");
2275 /* here we need to generate the equates for the
2276 register bank if required */
2277 if (FUNC_REGBANK (ftype) != rbank)
2281 rbank = FUNC_REGBANK (ftype);
2282 for (i = 0; i < mcs51_nRegs; i++)
2284 if (strcmp (regs8051[i].base, "0") == 0)
2285 emitcode ("", "%s = 0x%02x",
2287 8 * rbank + regs8051[i].offset);
2289 emitcode ("", "%s = %s + 0x%02x",
2292 8 * rbank + regs8051[i].offset);
2296 /* if this is an interrupt service routine then
2297 save acc, b, dpl, dph */
2298 if (IFFUNC_ISISR (sym->type))
2301 if (!inExcludeList ("acc"))
2302 emitcode ("push", "acc");
2303 if (!inExcludeList ("b"))
2304 emitcode ("push", "b");
2305 if (!inExcludeList ("dpl"))
2306 emitcode ("push", "dpl");
2307 if (!inExcludeList ("dph"))
2308 emitcode ("push", "dph");
2309 /* if this isr has no bank i.e. is going to
2310 run with bank 0 , then we need to save more
2312 if (!FUNC_REGBANK (sym->type))
2315 /* if this function does not call any other
2316 function then we can be economical and
2317 save only those registers that are used */
2318 if (!IFFUNC_HASFCALL(sym->type))
2322 /* if any registers used */
2325 /* save the registers used */
2326 for (i = 0; i < sym->regsUsed->size; i++)
2328 if (bitVectBitValue (sym->regsUsed, i) ||
2329 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2330 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2338 /* this function has a function call cannot
2339 determines register usage so we will have to push the
2341 saveRBank (0, ic, FALSE);
2342 if (options.parms_in_bank1) {
2344 for (i=0; i < 8 ; i++ ) {
2345 emitcode ("push","%s",rb1regs[i]);
2352 /* This ISR uses a non-zero bank.
2354 * We assume that the bank is available for our
2357 * However, if this ISR calls a function which uses some
2358 * other bank, we must save that bank entirely.
2360 unsigned long banksToSave = 0;
2362 if (IFFUNC_HASFCALL(sym->type))
2365 #define MAX_REGISTER_BANKS 4
2370 for (i = ic; i; i = i->next)
2372 if (i->op == ENDFUNCTION)
2374 /* we got to the end OK. */
2382 dtype = operandType (IC_LEFT(i));
2384 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2386 /* Mark this bank for saving. */
2387 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2389 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2393 banksToSave |= (1 << FUNC_REGBANK(dtype));
2396 /* And note that we don't need to do it in
2404 /* This is a mess; we have no idea what
2405 * register bank the called function might
2408 * The only thing I can think of to do is
2409 * throw a warning and hope.
2411 werror(W_FUNCPTR_IN_USING_ISR);
2415 if (banksToSave && options.useXstack)
2417 /* Since we aren't passing it an ic,
2418 * saveRBank will assume r0 is available to abuse.
2420 * So switch to our (trashable) bank now, so
2421 * the caller's R0 isn't trashed.
2423 emitcode ("push", "psw");
2424 emitcode ("mov", "psw,#0x%02x",
2425 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2429 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2431 if (banksToSave & (1 << ix))
2433 saveRBank(ix, NULL, FALSE);
2437 // jwk: this needs a closer look
2438 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2443 /* if callee-save to be used for this function
2444 then save the registers being used in this function */
2445 if (IFFUNC_CALLEESAVES(sym->type))
2449 /* if any registers used */
2452 /* save the registers used */
2453 for (i = 0; i < sym->regsUsed->size; i++)
2455 if (bitVectBitValue (sym->regsUsed, i) ||
2456 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2458 /* remember one saved register for later usage */
2459 if (calleesaves_saved_register < 0)
2460 calleesaves_saved_register = i;
2461 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2469 /* set the register bank to the desired value */
2470 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2473 emitcode ("push", "psw");
2474 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2477 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2480 if (options.useXstack)
2482 emitcode ("mov", "r0,%s", spname);
2483 emitcode ("mov", "a,_bp");
2484 emitcode ("movx", "@r0,a");
2485 emitcode ("inc", "%s", spname);
2489 /* set up the stack */
2490 emitcode ("push", "_bp"); /* save the callers stack */
2492 emitcode ("mov", "_bp,%s", spname);
2495 /* adjust the stack for the function */
2501 werror (W_STACK_OVERFLOW, sym->name);
2503 if (i > 3 && sym->recvSize < 4)
2506 emitcode ("mov", "a,sp");
2507 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2508 emitcode ("mov", "sp,a");
2513 if (IFFUNC_CALLEESAVES(sym->type))
2515 /* if it's a callee-saves function we need a saved register */
2516 if (calleesaves_saved_register >= 0)
2518 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2519 emitcode ("mov", "a,sp");
2520 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2521 emitcode ("mov", "sp,a");
2522 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2525 /* do it the hard way */
2527 emitcode ("inc", "sp");
2531 /* not callee-saves, we can clobber r0 */
2532 emitcode ("mov", "r0,a");
2533 emitcode ("mov", "a,sp");
2534 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2535 emitcode ("mov", "sp,a");
2536 emitcode ("mov", "a,r0");
2541 emitcode ("inc", "sp");
2547 emitcode ("mov", "a,_spx");
2548 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2549 emitcode ("mov", "_spx,a");
2554 /*-----------------------------------------------------------------*/
2555 /* genEndFunction - generates epilogue for functions */
2556 /*-----------------------------------------------------------------*/
2558 genEndFunction (iCode * ic)
2560 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2562 if (IFFUNC_ISNAKED(sym->type))
2564 emitcode(";", "naked function: no epilogue.");
2568 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2570 emitcode ("mov", "%s,_bp", spname);
2573 /* if use external stack but some variables were
2574 added to the local stack then decrement the
2576 if (options.useXstack && sym->stack)
2578 emitcode ("mov", "a,sp");
2579 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2580 emitcode ("mov", "sp,a");
2584 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2586 if (options.useXstack)
2588 emitcode ("mov", "r0,%s", spname);
2589 emitcode ("movx", "a,@r0");
2590 emitcode ("mov", "_bp,a");
2591 emitcode ("dec", "%s", spname);
2595 emitcode ("pop", "_bp");
2599 /* restore the register bank */
2600 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2602 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2603 || !options.useXstack)
2605 /* Special case of ISR using non-zero bank with useXstack
2608 emitcode ("pop", "psw");
2612 if (IFFUNC_ISISR (sym->type))
2615 /* now we need to restore the registers */
2616 /* if this isr has no bank i.e. is going to
2617 run with bank 0 , then we need to save more
2619 if (!FUNC_REGBANK (sym->type))
2621 /* if this function does not call any other
2622 function then we can be economical and
2623 save only those registers that are used */
2624 if (!IFFUNC_HASFCALL(sym->type))
2628 /* if any registers used */
2631 /* save the registers used */
2632 for (i = sym->regsUsed->size; i >= 0; i--)
2634 if (bitVectBitValue (sym->regsUsed, i) ||
2635 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2636 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2643 if (options.parms_in_bank1) {
2645 for (i = 7 ; i >= 0 ; i-- ) {
2646 emitcode ("pop","%s",rb1regs[i]);
2649 /* this function has a function call cannot
2650 determines register usage so we will have to pop the
2652 unsaveRBank (0, ic, FALSE);
2657 /* This ISR uses a non-zero bank.
2659 * Restore any register banks saved by genFunction
2662 // jwk: this needs a closer look
2663 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2666 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2668 if (savedBanks & (1 << ix))
2670 unsaveRBank(ix, NULL, FALSE);
2674 if (options.useXstack)
2676 /* Restore bank AFTER calling unsaveRBank,
2677 * since it can trash r0.
2679 emitcode ("pop", "psw");
2683 if (!inExcludeList ("dph"))
2684 emitcode ("pop", "dph");
2685 if (!inExcludeList ("dpl"))
2686 emitcode ("pop", "dpl");
2687 if (!inExcludeList ("b"))
2688 emitcode ("pop", "b");
2689 if (!inExcludeList ("acc"))
2690 emitcode ("pop", "acc");
2692 if (IFFUNC_ISCRITICAL (sym->type))
2693 emitcode ("setb", "ea");
2695 /* if debug then send end of function */
2696 if (options.debug && currFunc)
2699 emitcode ("", "C$%s$%d$%d$%d ==.",
2700 FileBaseName (ic->filename), currFunc->lastLine,
2701 ic->level, ic->block);
2702 if (IS_STATIC (currFunc->etype))
2703 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2705 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2709 emitcode ("reti", "");
2713 if (IFFUNC_ISCRITICAL (sym->type))
2714 emitcode ("setb", "ea");
2716 if (IFFUNC_CALLEESAVES(sym->type))
2720 /* if any registers used */
2723 /* save the registers used */
2724 for (i = sym->regsUsed->size; i >= 0; i--)
2726 if (bitVectBitValue (sym->regsUsed, i) ||
2727 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2728 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2734 /* if debug then send end of function */
2735 if (options.debug && currFunc)
2738 emitcode ("", "C$%s$%d$%d$%d ==.",
2739 FileBaseName (ic->filename), currFunc->lastLine,
2740 ic->level, ic->block);
2741 if (IS_STATIC (currFunc->etype))
2742 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2744 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2748 emitcode ("ret", "");
2753 /*-----------------------------------------------------------------*/
2754 /* genRet - generate code for return statement */
2755 /*-----------------------------------------------------------------*/
2759 int size, offset = 0, pushed = 0;
2761 D(emitcode ("; genRet",""));
2763 /* if we have no return value then
2764 just generate the "ret" */
2768 /* we have something to return then
2769 move the return value into place */
2770 aopOp (IC_LEFT (ic), ic, FALSE);
2771 size = AOP_SIZE (IC_LEFT (ic));
2776 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2779 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2781 emitcode ("push", "%s", l);
2786 l = aopGet (AOP (IC_LEFT (ic)), offset,
2788 if (strcmp (fReturn[offset], l))
2789 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2798 if (strcmp (fReturn[pushed], "a"))
2799 emitcode ("pop", fReturn[pushed]);
2801 emitcode ("pop", "acc");
2804 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2807 /* generate a jump to the return label
2808 if the next is not the return statement */
2809 if (!(ic->next && ic->next->op == LABEL &&
2810 IC_LABEL (ic->next) == returnLabel))
2812 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2816 /*-----------------------------------------------------------------*/
2817 /* genLabel - generates a label */
2818 /*-----------------------------------------------------------------*/
2820 genLabel (iCode * ic)
2822 /* special case never generate */
2823 if (IC_LABEL (ic) == entryLabel)
2826 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2829 /*-----------------------------------------------------------------*/
2830 /* genGoto - generates a ljmp */
2831 /*-----------------------------------------------------------------*/
2833 genGoto (iCode * ic)
2835 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2838 /*-----------------------------------------------------------------*/
2839 /* findLabelBackwards: walks back through the iCode chain looking */
2840 /* for the given label. Returns number of iCode instructions */
2841 /* between that label and given ic. */
2842 /* Returns zero if label not found. */
2843 /*-----------------------------------------------------------------*/
2845 findLabelBackwards (iCode * ic, int key)
2854 /* If we have any pushes or pops, we cannot predict the distance.
2855 I don't like this at all, this should be dealt with in the
2857 if (ic->op == IPUSH || ic->op == IPOP) {
2861 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2870 /*-----------------------------------------------------------------*/
2871 /* genPlusIncr :- does addition with increment if possible */
2872 /*-----------------------------------------------------------------*/
2874 genPlusIncr (iCode * ic)
2876 unsigned int icount;
2877 unsigned int size = getDataSize (IC_RESULT (ic));
2879 /* will try to generate an increment */
2880 /* if the right side is not a literal
2882 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2885 /* if the literal value of the right hand side
2886 is greater than 4 then it is not worth it */
2887 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2890 D(emitcode ("; genPlusIncr",""));
2892 /* if increment 16 bits in register */
2893 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2894 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2902 /* If the next instruction is a goto and the goto target
2903 * is < 10 instructions previous to this, we can generate
2904 * jumps straight to that target.
2906 if (ic->next && ic->next->op == GOTO
2907 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2908 && labelRange <= 10)
2910 emitcode (";", "tail increment optimized");
2911 tlbl = IC_LABEL (ic->next);
2916 tlbl = newiTempLabel (NULL);
2919 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2921 IS_AOP_PREG (IC_RESULT (ic)))
2922 emitcode ("cjne", "%s,#0x00,%05d$",
2923 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2927 emitcode ("clr", "a");
2928 emitcode ("cjne", "a,%s,%05d$",
2929 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2933 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2936 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2937 IS_AOP_PREG (IC_RESULT (ic)))
2938 emitcode ("cjne", "%s,#0x00,%05d$",
2939 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2942 emitcode ("cjne", "a,%s,%05d$",
2943 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2946 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2950 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2951 IS_AOP_PREG (IC_RESULT (ic)))
2952 emitcode ("cjne", "%s,#0x00,%05d$",
2953 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2957 emitcode ("cjne", "a,%s,%05d$",
2958 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2961 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2966 emitcode ("", "%05d$:", tlbl->key + 100);
2971 /* if the sizes are greater than 1 then we cannot */
2972 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2973 AOP_SIZE (IC_LEFT (ic)) > 1)
2976 /* we can if the aops of the left & result match or
2977 if they are in registers and the registers are the
2979 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2984 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2985 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2986 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2992 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3001 /*-----------------------------------------------------------------*/
3002 /* outBitAcc - output a bit in acc */
3003 /*-----------------------------------------------------------------*/
3005 outBitAcc (operand * result)
3007 symbol *tlbl = newiTempLabel (NULL);
3008 /* if the result is a bit */
3009 if (AOP_TYPE (result) == AOP_CRY)
3011 aopPut (AOP (result), "a", 0);
3015 emitcode ("jz", "%05d$", tlbl->key + 100);
3016 emitcode ("mov", "a,%s", one);
3017 emitcode ("", "%05d$:", tlbl->key + 100);
3022 /*-----------------------------------------------------------------*/
3023 /* genPlusBits - generates code for addition of two bits */
3024 /*-----------------------------------------------------------------*/
3026 genPlusBits (iCode * ic)
3028 D(emitcode ("; genPlusBits",""));
3030 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3032 symbol *lbl = newiTempLabel (NULL);
3033 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3034 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3035 emitcode ("cpl", "c");
3036 emitcode ("", "%05d$:", (lbl->key + 100));
3037 outBitC (IC_RESULT (ic));
3041 emitcode ("clr", "a");
3042 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3043 emitcode ("rlc", "a");
3044 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3045 emitcode ("addc", "a,#0x00");
3046 outAcc (IC_RESULT (ic));
3051 /* This is the original version of this code.
3053 * This is being kept around for reference,
3054 * because I am not entirely sure I got it right...
3057 adjustArithmeticResult (iCode * ic)
3059 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3060 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3061 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3062 aopPut (AOP (IC_RESULT (ic)),
3063 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3066 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3067 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3068 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3069 aopPut (AOP (IC_RESULT (ic)),
3070 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3073 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3074 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3075 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3076 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3077 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3080 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3081 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3085 /* This is the pure and virtuous version of this code.
3086 * I'm pretty certain it's right, but not enough to toss the old
3090 adjustArithmeticResult (iCode * ic)
3092 if (opIsGptr (IC_RESULT (ic)) &&
3093 opIsGptr (IC_LEFT (ic)) &&
3094 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3096 aopPut (AOP (IC_RESULT (ic)),
3097 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3101 if (opIsGptr (IC_RESULT (ic)) &&
3102 opIsGptr (IC_RIGHT (ic)) &&
3103 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3105 aopPut (AOP (IC_RESULT (ic)),
3106 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3110 if (opIsGptr (IC_RESULT (ic)) &&
3111 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3112 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3113 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3117 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3118 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3123 /*-----------------------------------------------------------------*/
3124 /* genPlus - generates code for addition */
3125 /*-----------------------------------------------------------------*/
3127 genPlus (iCode * ic)
3129 int size, offset = 0;
3131 asmop *leftOp, *rightOp;
3133 /* special cases :- */
3135 D(emitcode ("; genPlus",""));
3137 aopOp (IC_LEFT (ic), ic, FALSE);
3138 aopOp (IC_RIGHT (ic), ic, FALSE);
3139 aopOp (IC_RESULT (ic), ic, TRUE);
3141 /* if literal, literal on the right or
3142 if left requires ACC or right is already
3144 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3145 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3146 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3148 operand *t = IC_RIGHT (ic);
3149 IC_RIGHT (ic) = IC_LEFT (ic);
3153 /* if both left & right are in bit
3155 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3156 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3162 /* if left in bit space & right literal */
3163 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3164 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3166 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3167 /* if result in bit space */
3168 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3170 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3171 emitcode ("cpl", "c");
3172 outBitC (IC_RESULT (ic));
3176 size = getDataSize (IC_RESULT (ic));
3179 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3180 emitcode ("addc", "a,#00");
3181 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3187 /* if I can do an increment instead
3188 of add then GOOD for ME */
3189 if (genPlusIncr (ic) == TRUE)
3192 size = getDataSize (IC_RESULT (ic));
3194 leftOp = AOP(IC_LEFT(ic));
3195 rightOp = AOP(IC_RIGHT(ic));
3200 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3202 emitcode("mov", "b,a");
3203 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3204 emitcode("xch", "a,b");
3205 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3206 emitcode (add, "a,b");
3208 else if (aopGetUsesAcc (leftOp, offset))
3210 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3211 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3215 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3216 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3218 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3219 add = "addc"; /* further adds must propagate carry */
3222 adjustArithmeticResult (ic);
3225 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3226 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3227 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3230 /*-----------------------------------------------------------------*/
3231 /* genMinusDec :- does subtraction with deccrement if possible */
3232 /*-----------------------------------------------------------------*/
3234 genMinusDec (iCode * ic)
3236 unsigned int icount;
3237 unsigned int size = getDataSize (IC_RESULT (ic));
3239 /* will try to generate an increment */
3240 /* if the right side is not a literal
3242 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3245 /* if the literal value of the right hand side
3246 is greater than 4 then it is not worth it */
3247 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3250 D(emitcode ("; genMinusDec",""));
3252 /* if decrement 16 bits in register */
3253 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3254 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3262 /* If the next instruction is a goto and the goto target
3263 * is <= 10 instructions previous to this, we can generate
3264 * jumps straight to that target.
3266 if (ic->next && ic->next->op == GOTO
3267 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3268 && labelRange <= 10)
3270 emitcode (";", "tail decrement optimized");
3271 tlbl = IC_LABEL (ic->next);
3276 tlbl = newiTempLabel (NULL);
3280 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3281 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3282 IS_AOP_PREG (IC_RESULT (ic)))
3283 emitcode ("cjne", "%s,#0xff,%05d$"
3284 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3288 emitcode ("mov", "a,#0xff");
3289 emitcode ("cjne", "a,%s,%05d$"
3290 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3293 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3296 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3297 IS_AOP_PREG (IC_RESULT (ic)))
3298 emitcode ("cjne", "%s,#0xff,%05d$"
3299 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3303 emitcode ("cjne", "a,%s,%05d$"
3304 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3307 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3311 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3312 IS_AOP_PREG (IC_RESULT (ic)))
3313 emitcode ("cjne", "%s,#0xff,%05d$"
3314 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3318 emitcode ("cjne", "a,%s,%05d$"
3319 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3322 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3326 emitcode ("", "%05d$:", tlbl->key + 100);
3331 /* if the sizes are greater than 1 then we cannot */
3332 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3333 AOP_SIZE (IC_LEFT (ic)) > 1)
3336 /* we can if the aops of the left & result match or
3337 if they are in registers and the registers are the
3339 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3343 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3351 /*-----------------------------------------------------------------*/
3352 /* addSign - complete with sign */
3353 /*-----------------------------------------------------------------*/
3355 addSign (operand * result, int offset, int sign)
3357 int size = (getDataSize (result) - offset);
3362 emitcode ("rlc", "a");
3363 emitcode ("subb", "a,acc");
3365 aopPut (AOP (result), "a", offset++);
3369 aopPut (AOP (result), zero, offset++);
3373 /*-----------------------------------------------------------------*/
3374 /* genMinusBits - generates code for subtraction of two bits */
3375 /*-----------------------------------------------------------------*/
3377 genMinusBits (iCode * ic)
3379 symbol *lbl = newiTempLabel (NULL);
3381 D(emitcode ("; genMinusBits",""));
3383 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3385 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3386 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3387 emitcode ("cpl", "c");
3388 emitcode ("", "%05d$:", (lbl->key + 100));
3389 outBitC (IC_RESULT (ic));
3393 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3394 emitcode ("subb", "a,acc");
3395 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3396 emitcode ("inc", "a");
3397 emitcode ("", "%05d$:", (lbl->key + 100));
3398 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3399 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3403 /*-----------------------------------------------------------------*/
3404 /* genMinus - generates code for subtraction */
3405 /*-----------------------------------------------------------------*/
3407 genMinus (iCode * ic)
3409 int size, offset = 0;
3411 D(emitcode ("; genMinus",""));
3413 aopOp (IC_LEFT (ic), ic, FALSE);
3414 aopOp (IC_RIGHT (ic), ic, FALSE);
3415 aopOp (IC_RESULT (ic), ic, TRUE);
3417 /* special cases :- */
3418 /* if both left & right are in bit space */
3419 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3420 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3426 /* if I can do an decrement instead
3427 of subtract then GOOD for ME */
3428 if (genMinusDec (ic) == TRUE)
3431 size = getDataSize (IC_RESULT (ic));
3433 /* if literal, add a,#-lit, else normal subb */
3434 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3436 unsigned long lit = 0L;
3438 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3443 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3444 /* first add without previous c */
3446 if (!size && lit==-1) {
3447 emitcode ("dec", "a");
3449 emitcode ("add", "a,#0x%02x",
3450 (unsigned int) (lit & 0x0FFL));
3453 emitcode ("addc", "a,#0x%02x",
3454 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3456 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3461 asmop *leftOp, *rightOp;
3463 leftOp = AOP(IC_LEFT(ic));
3464 rightOp = AOP(IC_RIGHT(ic));
3468 if (aopGetUsesAcc(rightOp, offset)) {
3469 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3470 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3472 emitcode( "cpl", "c");
3474 emitcode( "setb", "c");
3476 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3477 emitcode("cpl", "a");
3479 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3482 emitcode ("subb", "a,%s",
3483 aopGet(rightOp, offset, FALSE, TRUE));
3486 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3491 adjustArithmeticResult (ic);
3494 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3495 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3496 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3500 /*-----------------------------------------------------------------*/
3501 /* genMultbits :- multiplication of bits */
3502 /*-----------------------------------------------------------------*/
3504 genMultbits (operand * left,
3508 D(emitcode ("; genMultbits",""));
3510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3511 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3516 /*-----------------------------------------------------------------*/
3517 /* genMultOneByte : 8*8=8/16 bit multiplication */
3518 /*-----------------------------------------------------------------*/
3520 genMultOneByte (operand * left,
3524 sym_link *opetype = operandType (result);
3526 int size=AOP_SIZE(result);
3528 D(emitcode ("; genMultOneByte",""));
3530 if (size<1 || size>2) {
3531 // this should never happen
3532 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3533 AOP_SIZE(result), __FILE__, lineno);
3537 /* (if two literals: the value is computed before) */
3538 /* if one literal, literal on the right */
3539 if (AOP_TYPE (left) == AOP_LIT)
3544 //emitcode (";", "swapped left and right");
3547 if (SPEC_USIGN(opetype)
3548 // ignore the sign of left and right, what else can we do?
3549 || (SPEC_USIGN(operandType(left)) &&
3550 SPEC_USIGN(operandType(right)))) {
3551 // just an unsigned 8*8=8/16 multiply
3552 //emitcode (";","unsigned");
3553 // TODO: check for accumulator clash between left & right aops?
3554 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3555 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3556 emitcode ("mul", "ab");
3557 aopPut (AOP (result), "a", 0);
3559 aopPut (AOP (result), "b", 1);
3564 // we have to do a signed multiply
3566 //emitcode (";", "signed");
3567 emitcode ("clr", "F0"); // reset sign flag
3568 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3570 lbl=newiTempLabel(NULL);
3571 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3572 // left side is negative, 8-bit two's complement, this fails for -128
3573 emitcode ("setb", "F0"); // set sign flag
3574 emitcode ("cpl", "a");
3575 emitcode ("inc", "a");
3577 emitcode ("", "%05d$:", lbl->key+100);
3580 if (AOP_TYPE(right)==AOP_LIT) {
3581 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3582 /* AND literal negative */
3584 emitcode ("cpl", "F0"); // complement sign flag
3585 emitcode ("mov", "b,#0x%02x", -val);
3587 emitcode ("mov", "b,#0x%02x", val);
3590 lbl=newiTempLabel(NULL);
3591 emitcode ("mov", "b,a");
3592 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3593 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3594 // right side is negative, 8-bit two's complement
3595 emitcode ("cpl", "F0"); // complement sign flag
3596 emitcode ("cpl", "a");
3597 emitcode ("inc", "a");
3598 emitcode ("", "%05d$:", lbl->key+100);
3600 emitcode ("mul", "ab");
3602 lbl=newiTempLabel(NULL);
3603 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3604 // only ONE op was negative, we have to do a 8/16-bit two's complement
3605 emitcode ("cpl", "a"); // lsb
3607 emitcode ("inc", "a");
3609 emitcode ("add", "a,#1");
3610 emitcode ("xch", "a,b");
3611 emitcode ("cpl", "a"); // msb
3612 emitcode ("addc", "a,#0");
3613 emitcode ("xch", "a,b");
3616 emitcode ("", "%05d$:", lbl->key+100);
3617 aopPut (AOP (result), "a", 0);
3619 aopPut (AOP (result), "b", 1);
3623 /*-----------------------------------------------------------------*/
3624 /* genMult - generates code for multiplication */
3625 /*-----------------------------------------------------------------*/
3627 genMult (iCode * ic)
3629 operand *left = IC_LEFT (ic);
3630 operand *right = IC_RIGHT (ic);
3631 operand *result = IC_RESULT (ic);
3633 D(emitcode ("; genMult",""));
3635 /* assign the amsops */
3636 aopOp (left, ic, FALSE);
3637 aopOp (right, ic, FALSE);
3638 aopOp (result, ic, TRUE);
3640 /* special cases first */
3642 if (AOP_TYPE (left) == AOP_CRY &&
3643 AOP_TYPE (right) == AOP_CRY)
3645 genMultbits (left, right, result);
3649 /* if both are of size == 1 */
3650 #if 0 // one of them can be a sloc shared with the result
3651 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3653 if (getSize(operandType(left)) == 1 &&
3654 getSize(operandType(right)) == 1)
3657 genMultOneByte (left, right, result);
3661 /* should have been converted to function call */
3662 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3663 getSize(OP_SYMBOL(right)->type));
3667 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (result, NULL, ic, TRUE);
3672 /*-----------------------------------------------------------------*/
3673 /* genDivbits :- division of bits */
3674 /*-----------------------------------------------------------------*/
3676 genDivbits (operand * left,
3683 D(emitcode ("; genDivbits",""));
3685 /* the result must be bit */
3686 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3687 l = aopGet (AOP (left), 0, FALSE, FALSE);
3691 emitcode ("div", "ab");
3692 emitcode ("rrc", "a");
3693 aopPut (AOP (result), "c", 0);
3696 /*-----------------------------------------------------------------*/
3697 /* genDivOneByte : 8 bit division */
3698 /*-----------------------------------------------------------------*/
3700 genDivOneByte (operand * left,
3704 sym_link *opetype = operandType (result);
3709 D(emitcode ("; genDivOneByte",""));
3711 size = AOP_SIZE (result) - 1;
3713 /* signed or unsigned */
3714 if (SPEC_USIGN (opetype))
3716 /* unsigned is easy */
3717 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3718 l = aopGet (AOP (left), 0, FALSE, FALSE);
3720 emitcode ("div", "ab");
3721 aopPut (AOP (result), "a", 0);
3723 aopPut (AOP (result), zero, offset++);
3727 /* signed is a little bit more difficult */
3729 /* save the signs of the operands */
3730 l = aopGet (AOP (left), 0, FALSE, FALSE);
3732 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3733 emitcode ("push", "acc"); /* save it on the stack */
3735 /* now sign adjust for both left & right */
3736 l = aopGet (AOP (right), 0, FALSE, FALSE);
3738 lbl = newiTempLabel (NULL);
3739 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3740 emitcode ("cpl", "a");
3741 emitcode ("inc", "a");
3742 emitcode ("", "%05d$:", (lbl->key + 100));
3743 emitcode ("mov", "b,a");
3745 /* sign adjust left side */
3746 l = aopGet (AOP (left), 0, FALSE, FALSE);
3749 lbl = newiTempLabel (NULL);
3750 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3751 emitcode ("cpl", "a");
3752 emitcode ("inc", "a");
3753 emitcode ("", "%05d$:", (lbl->key + 100));
3755 /* now the division */
3756 emitcode ("div", "ab");
3757 /* we are interested in the lower order
3759 emitcode ("mov", "b,a");
3760 lbl = newiTempLabel (NULL);
3761 emitcode ("pop", "acc");
3762 /* if there was an over flow we don't
3763 adjust the sign of the result */
3764 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3765 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3767 emitcode ("clr", "a");
3768 emitcode ("subb", "a,b");
3769 emitcode ("mov", "b,a");
3770 emitcode ("", "%05d$:", (lbl->key + 100));
3772 /* now we are done */
3773 aopPut (AOP (result), "b", 0);
3776 emitcode ("mov", "c,b.7");
3777 emitcode ("subb", "a,acc");
3780 aopPut (AOP (result), "a", offset++);
3784 /*-----------------------------------------------------------------*/
3785 /* genDiv - generates code for division */
3786 /*-----------------------------------------------------------------*/
3790 operand *left = IC_LEFT (ic);
3791 operand *right = IC_RIGHT (ic);
3792 operand *result = IC_RESULT (ic);
3794 D(emitcode ("; genDiv",""));
3796 /* assign the amsops */
3797 aopOp (left, ic, FALSE);
3798 aopOp (right, ic, FALSE);
3799 aopOp (result, ic, TRUE);
3801 /* special cases first */
3803 if (AOP_TYPE (left) == AOP_CRY &&
3804 AOP_TYPE (right) == AOP_CRY)
3806 genDivbits (left, right, result);
3810 /* if both are of size == 1 */
3811 if (AOP_SIZE (left) == 1 &&
3812 AOP_SIZE (right) == 1)
3814 genDivOneByte (left, right, result);
3818 /* should have been converted to function call */
3821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (result, NULL, ic, TRUE);
3826 /*-----------------------------------------------------------------*/
3827 /* genModbits :- modulus of bits */
3828 /*-----------------------------------------------------------------*/
3830 genModbits (operand * left,
3837 D(emitcode ("; genModbits",""));
3839 /* the result must be bit */
3840 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3841 l = aopGet (AOP (left), 0, FALSE, FALSE);
3845 emitcode ("div", "ab");
3846 emitcode ("mov", "a,b");
3847 emitcode ("rrc", "a");
3848 aopPut (AOP (result), "c", 0);
3851 /*-----------------------------------------------------------------*/
3852 /* genModOneByte : 8 bit modulus */
3853 /*-----------------------------------------------------------------*/
3855 genModOneByte (operand * left,
3859 sym_link *opetype = operandType (result);
3863 D(emitcode ("; genModOneByte",""));
3865 /* signed or unsigned */
3866 if (SPEC_USIGN (opetype))
3868 /* unsigned is easy */
3869 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3870 l = aopGet (AOP (left), 0, FALSE, FALSE);
3872 emitcode ("div", "ab");
3873 aopPut (AOP (result), "b", 0);
3877 /* signed is a little bit more difficult */
3879 /* save the signs of the operands */
3880 l = aopGet (AOP (left), 0, FALSE, FALSE);
3883 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3884 emitcode ("push", "acc"); /* save it on the stack */
3886 /* now sign adjust for both left & right */
3887 l = aopGet (AOP (right), 0, FALSE, FALSE);
3890 lbl = newiTempLabel (NULL);
3891 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3892 emitcode ("cpl", "a");
3893 emitcode ("inc", "a");
3894 emitcode ("", "%05d$:", (lbl->key + 100));
3895 emitcode ("mov", "b,a");
3897 /* sign adjust left side */
3898 l = aopGet (AOP (left), 0, FALSE, FALSE);
3901 lbl = newiTempLabel (NULL);
3902 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3903 emitcode ("cpl", "a");
3904 emitcode ("inc", "a");
3905 emitcode ("", "%05d$:", (lbl->key + 100));
3907 /* now the multiplication */
3908 emitcode ("div", "ab");
3909 /* we are interested in the lower order
3911 lbl = newiTempLabel (NULL);
3912 emitcode ("pop", "acc");
3913 /* if there was an over flow we don't
3914 adjust the sign of the result */
3915 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3916 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3918 emitcode ("clr", "a");
3919 emitcode ("subb", "a,b");
3920 emitcode ("mov", "b,a");
3921 emitcode ("", "%05d$:", (lbl->key + 100));
3923 /* now we are done */
3924 aopPut (AOP (result), "b", 0);
3928 /*-----------------------------------------------------------------*/
3929 /* genMod - generates code for division */
3930 /*-----------------------------------------------------------------*/
3934 operand *left = IC_LEFT (ic);
3935 operand *right = IC_RIGHT (ic);
3936 operand *result = IC_RESULT (ic);
3938 D(emitcode ("; genMod",""));
3940 /* assign the amsops */
3941 aopOp (left, ic, FALSE);
3942 aopOp (right, ic, FALSE);
3943 aopOp (result, ic, TRUE);
3945 /* special cases first */
3947 if (AOP_TYPE (left) == AOP_CRY &&
3948 AOP_TYPE (right) == AOP_CRY)
3950 genModbits (left, right, result);
3954 /* if both are of size == 1 */
3955 if (AOP_SIZE (left) == 1 &&
3956 AOP_SIZE (right) == 1)
3958 genModOneByte (left, right, result);
3962 /* should have been converted to function call */
3966 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3968 freeAsmop (result, NULL, ic, TRUE);
3971 /*-----------------------------------------------------------------*/
3972 /* genIfxJump :- will create a jump depending on the ifx */
3973 /*-----------------------------------------------------------------*/
3975 genIfxJump (iCode * ic, char *jval)
3978 symbol *tlbl = newiTempLabel (NULL);
3981 D(emitcode ("; genIfxJump",""));
3983 /* if true label then we jump if condition
3987 jlbl = IC_TRUE (ic);
3988 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3989 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3993 /* false label is present */
3994 jlbl = IC_FALSE (ic);
3995 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3996 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3998 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3999 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4001 emitcode (inst, "%05d$", tlbl->key + 100);
4002 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4003 emitcode ("", "%05d$:", tlbl->key + 100);
4005 /* mark the icode as generated */
4009 /*-----------------------------------------------------------------*/
4010 /* genCmp :- greater or less than comparison */
4011 /*-----------------------------------------------------------------*/
4013 genCmp (operand * left, operand * right,
4014 operand * result, iCode * ifx, int sign, iCode *ic)
4016 int size, offset = 0;
4017 unsigned long lit = 0L;
4019 D(emitcode ("; genCmp",""));
4021 /* if left & right are bit variables */
4022 if (AOP_TYPE (left) == AOP_CRY &&
4023 AOP_TYPE (right) == AOP_CRY)
4025 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4026 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4030 /* subtract right from left if at the
4031 end the carry flag is set then we know that
4032 left is greater than right */
4033 size = max (AOP_SIZE (left), AOP_SIZE (right));
4035 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4036 if ((size == 1) && !sign &&
4037 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4039 symbol *lbl = newiTempLabel (NULL);
4040 emitcode ("cjne", "%s,%s,%05d$",
4041 aopGet (AOP (left), offset, FALSE, FALSE),
4042 aopGet (AOP (right), offset, FALSE, FALSE),
4044 emitcode ("", "%05d$:", lbl->key + 100);
4048 if (AOP_TYPE (right) == AOP_LIT)
4050 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4051 /* optimize if(x < 0) or if(x >= 0) */
4060 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4061 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4063 genIfxJump (ifx, "acc.7");
4067 emitcode ("rlc", "a");
4075 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4076 if (sign && size == 0)
4078 emitcode ("xrl", "a,#0x80");
4079 if (AOP_TYPE (right) == AOP_LIT)
4081 unsigned long lit = (unsigned long)
4082 floatFromVal (AOP (right)->aopu.aop_lit);
4083 emitcode ("subb", "a,#0x%02x",
4084 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4088 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4089 emitcode ("xrl", "b,#0x80");
4090 emitcode ("subb", "a,b");
4094 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4108 /* if the result is used in the next
4109 ifx conditional branch then generate
4110 code a little differently */
4112 genIfxJump (ifx, "c");
4115 /* leave the result in acc */
4119 /*-----------------------------------------------------------------*/
4120 /* genCmpGt :- greater than comparison */
4121 /*-----------------------------------------------------------------*/
4123 genCmpGt (iCode * ic, iCode * ifx)
4125 operand *left, *right, *result;
4126 sym_link *letype, *retype;
4129 D(emitcode ("; genCmpGt",""));
4131 left = IC_LEFT (ic);
4132 right = IC_RIGHT (ic);
4133 result = IC_RESULT (ic);
4135 letype = getSpec (operandType (left));
4136 retype = getSpec (operandType (right));
4137 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4138 /* assign the amsops */
4139 aopOp (left, ic, FALSE);
4140 aopOp (right, ic, FALSE);
4141 aopOp (result, ic, TRUE);
4143 genCmp (right, left, result, ifx, sign,ic);
4145 freeAsmop (result, NULL, ic, TRUE);
4148 /*-----------------------------------------------------------------*/
4149 /* genCmpLt - less than comparisons */
4150 /*-----------------------------------------------------------------*/
4152 genCmpLt (iCode * ic, iCode * ifx)
4154 operand *left, *right, *result;
4155 sym_link *letype, *retype;
4158 D(emitcode ("; genCmpLt",""));
4160 left = IC_LEFT (ic);
4161 right = IC_RIGHT (ic);
4162 result = IC_RESULT (ic);
4164 letype = getSpec (operandType (left));
4165 retype = getSpec (operandType (right));
4166 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4168 /* assign the amsops */
4169 aopOp (left, ic, FALSE);
4170 aopOp (right, ic, FALSE);
4171 aopOp (result, ic, TRUE);
4173 genCmp (left, right, result, ifx, sign,ic);
4175 freeAsmop (result, NULL, ic, TRUE);
4178 /*-----------------------------------------------------------------*/
4179 /* gencjneshort - compare and jump if not equal */
4180 /*-----------------------------------------------------------------*/
4182 gencjneshort (operand * left, operand * right, symbol * lbl)
4184 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4186 unsigned long lit = 0L;
4188 /* if the left side is a literal or
4189 if the right is in a pointer register and left
4191 if ((AOP_TYPE (left) == AOP_LIT) ||
4192 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4198 if (AOP_TYPE (right) == AOP_LIT)
4199 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4201 /* if the right side is a literal then anything goes */
4202 if (AOP_TYPE (right) == AOP_LIT &&
4203 AOP_TYPE (left) != AOP_DIR)
4207 emitcode ("cjne", "%s,%s,%05d$",
4208 aopGet (AOP (left), offset, FALSE, FALSE),
4209 aopGet (AOP (right), offset, FALSE, FALSE),
4215 /* if the right side is in a register or in direct space or
4216 if the left is a pointer register & right is not */
4217 else if (AOP_TYPE (right) == AOP_REG ||
4218 AOP_TYPE (right) == AOP_DIR ||
4219 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4220 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4224 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4225 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4226 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4227 emitcode ("jnz", "%05d$", lbl->key + 100);
4229 emitcode ("cjne", "a,%s,%05d$",
4230 aopGet (AOP (right), offset, FALSE, TRUE),
4237 /* right is a pointer reg need both a & b */
4240 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4241 if (strcmp (l, "b"))
4242 emitcode ("mov", "b,%s", l);
4243 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4244 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4250 /*-----------------------------------------------------------------*/
4251 /* gencjne - compare and jump if not equal */
4252 /*-----------------------------------------------------------------*/
4254 gencjne (operand * left, operand * right, symbol * lbl)
4256 symbol *tlbl = newiTempLabel (NULL);
4258 gencjneshort (left, right, lbl);
4260 emitcode ("mov", "a,%s", one);
4261 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4262 emitcode ("", "%05d$:", lbl->key + 100);
4263 emitcode ("clr", "a");
4264 emitcode ("", "%05d$:", tlbl->key + 100);
4267 /*-----------------------------------------------------------------*/
4268 /* genCmpEq - generates code for equal to */
4269 /*-----------------------------------------------------------------*/
4271 genCmpEq (iCode * ic, iCode * ifx)
4273 operand *left, *right, *result;
4275 D(emitcode ("; genCmpEq",""));
4277 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4278 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4279 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4281 /* if literal, literal on the right or
4282 if the right is in a pointer register and left
4284 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4285 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4287 operand *t = IC_RIGHT (ic);
4288 IC_RIGHT (ic) = IC_LEFT (ic);
4292 if (ifx && !AOP_SIZE (result))
4295 /* if they are both bit variables */
4296 if (AOP_TYPE (left) == AOP_CRY &&
4297 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4299 if (AOP_TYPE (right) == AOP_LIT)
4301 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4304 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4305 emitcode ("cpl", "c");
4309 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4313 emitcode ("clr", "c");
4315 /* AOP_TYPE(right) == AOP_CRY */
4319 symbol *lbl = newiTempLabel (NULL);
4320 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4321 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4322 emitcode ("cpl", "c");
4323 emitcode ("", "%05d$:", (lbl->key + 100));
4325 /* if true label then we jump if condition
4327 tlbl = newiTempLabel (NULL);
4330 emitcode ("jnc", "%05d$", tlbl->key + 100);
4331 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4335 emitcode ("jc", "%05d$", tlbl->key + 100);
4336 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4338 emitcode ("", "%05d$:", tlbl->key + 100);
4342 tlbl = newiTempLabel (NULL);
4343 gencjneshort (left, right, tlbl);
4346 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4347 emitcode ("", "%05d$:", tlbl->key + 100);
4351 symbol *lbl = newiTempLabel (NULL);
4352 emitcode ("sjmp", "%05d$", lbl->key + 100);
4353 emitcode ("", "%05d$:", tlbl->key + 100);
4354 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4355 emitcode ("", "%05d$:", lbl->key + 100);
4358 /* mark the icode as generated */
4363 /* if they are both bit variables */
4364 if (AOP_TYPE (left) == AOP_CRY &&
4365 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4367 if (AOP_TYPE (right) == AOP_LIT)
4369 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4372 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4373 emitcode ("cpl", "c");
4377 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4381 emitcode ("clr", "c");
4383 /* AOP_TYPE(right) == AOP_CRY */
4387 symbol *lbl = newiTempLabel (NULL);
4388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4389 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4390 emitcode ("cpl", "c");
4391 emitcode ("", "%05d$:", (lbl->key + 100));
4394 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4401 genIfxJump (ifx, "c");
4404 /* if the result is used in an arithmetic operation
4405 then put the result in place */
4410 gencjne (left, right, newiTempLabel (NULL));
4411 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4413 aopPut (AOP (result), "a", 0);
4418 genIfxJump (ifx, "a");
4421 /* if the result is used in an arithmetic operation
4422 then put the result in place */
4423 if (AOP_TYPE (result) != AOP_CRY)
4425 /* leave the result in acc */
4429 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4431 freeAsmop (result, NULL, ic, TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* ifxForOp - returns the icode containing the ifx for operand */
4436 /*-----------------------------------------------------------------*/
4438 ifxForOp (operand * op, iCode * ic)
4440 /* if true symbol then needs to be assigned */
4441 if (IS_TRUE_SYMOP (op))
4444 /* if this has register type condition and
4445 the next instruction is ifx with the same operand
4446 and live to of the operand is upto the ifx only then */
4448 ic->next->op == IFX &&
4449 IC_COND (ic->next)->key == op->key &&
4450 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4456 /*-----------------------------------------------------------------*/
4457 /* hasInc - operand is incremented before any other use */
4458 /*-----------------------------------------------------------------*/
4460 hasInc (operand *op, iCode *ic,int osize)
4462 sym_link *type = operandType(op);
4463 sym_link *retype = getSpec (type);
4464 iCode *lic = ic->next;
4467 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4468 if (!IS_SYMOP(op)) return NULL;
4470 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4471 if (IS_AGGREGATE(type->next)) return NULL;
4472 if (osize != (isize = getSize(type->next))) return NULL;
4475 /* if operand of the form op = op + <sizeof *op> */
4476 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4477 isOperandEqual(IC_RESULT(lic),op) &&
4478 isOperandLiteral(IC_RIGHT(lic)) &&
4479 operandLitValue(IC_RIGHT(lic)) == isize) {
4482 /* if the operand used or deffed */
4483 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4486 /* if GOTO or IFX */
4487 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4493 /*-----------------------------------------------------------------*/
4494 /* genAndOp - for && operation */
4495 /*-----------------------------------------------------------------*/
4497 genAndOp (iCode * ic)
4499 operand *left, *right, *result;
4502 D(emitcode ("; genAndOp",""));
4504 /* note here that && operations that are in an
4505 if statement are taken away by backPatchLabels
4506 only those used in arthmetic operations remain */
4507 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4508 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4509 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4511 /* if both are bit variables */
4512 if (AOP_TYPE (left) == AOP_CRY &&
4513 AOP_TYPE (right) == AOP_CRY)
4515 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4516 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4521 tlbl = newiTempLabel (NULL);
4523 emitcode ("jz", "%05d$", tlbl->key + 100);
4525 emitcode ("", "%05d$:", tlbl->key + 100);
4529 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531 freeAsmop (result, NULL, ic, TRUE);
4535 /*-----------------------------------------------------------------*/
4536 /* genOrOp - for || operation */
4537 /*-----------------------------------------------------------------*/
4539 genOrOp (iCode * ic)
4541 operand *left, *right, *result;
4544 D(emitcode ("; genOrOp",""));
4546 /* note here that || operations that are in an
4547 if statement are taken away by backPatchLabels
4548 only those used in arthmetic operations remain */
4549 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4550 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4551 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4553 /* if both are bit variables */
4554 if (AOP_TYPE (left) == AOP_CRY &&
4555 AOP_TYPE (right) == AOP_CRY)
4557 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4558 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4563 tlbl = newiTempLabel (NULL);
4565 emitcode ("jnz", "%05d$", tlbl->key + 100);
4567 emitcode ("", "%05d$:", tlbl->key + 100);
4571 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4572 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4573 freeAsmop (result, NULL, ic, TRUE);
4576 /*-----------------------------------------------------------------*/
4577 /* isLiteralBit - test if lit == 2^n */
4578 /*-----------------------------------------------------------------*/
4580 isLiteralBit (unsigned long lit)
4582 unsigned long pw[32] =
4583 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4584 0x100L, 0x200L, 0x400L, 0x800L,
4585 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4586 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4587 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4588 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4589 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4592 for (idx = 0; idx < 32; idx++)
4598 /*-----------------------------------------------------------------*/
4599 /* continueIfTrue - */
4600 /*-----------------------------------------------------------------*/
4602 continueIfTrue (iCode * ic)
4605 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4609 /*-----------------------------------------------------------------*/
4611 /*-----------------------------------------------------------------*/
4613 jumpIfTrue (iCode * ic)
4616 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4620 /*-----------------------------------------------------------------*/
4621 /* jmpTrueOrFalse - */
4622 /*-----------------------------------------------------------------*/
4624 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4626 // ugly but optimized by peephole
4629 symbol *nlbl = newiTempLabel (NULL);
4630 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4631 emitcode ("", "%05d$:", tlbl->key + 100);
4632 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4633 emitcode ("", "%05d$:", nlbl->key + 100);
4637 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4638 emitcode ("", "%05d$:", tlbl->key + 100);
4643 /*-----------------------------------------------------------------*/
4644 /* genAnd - code for and */
4645 /*-----------------------------------------------------------------*/
4647 genAnd (iCode * ic, iCode * ifx)
4649 operand *left, *right, *result;
4650 int size, offset = 0;
4651 unsigned long lit = 0L;
4655 D(emitcode ("; genAnd",""));
4657 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4658 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4659 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4662 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4664 AOP_TYPE (left), AOP_TYPE (right));
4665 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4667 AOP_SIZE (left), AOP_SIZE (right));
4670 /* if left is a literal & right is not then exchange them */
4671 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4672 AOP_NEEDSACC (left))
4674 operand *tmp = right;
4679 /* if result = right then exchange them */
4680 if (sameRegs (AOP (result), AOP (right)))
4682 operand *tmp = right;
4687 /* if right is bit then exchange them */
4688 if (AOP_TYPE (right) == AOP_CRY &&
4689 AOP_TYPE (left) != AOP_CRY)
4691 operand *tmp = right;
4695 if (AOP_TYPE (right) == AOP_LIT)
4696 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4698 size = AOP_SIZE (result);
4701 // result = bit & yy;
4702 if (AOP_TYPE (left) == AOP_CRY)
4704 // c = bit & literal;
4705 if (AOP_TYPE (right) == AOP_LIT)
4709 if (size && sameRegs (AOP (result), AOP (left)))
4712 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4717 if (size && (AOP_TYPE (result) == AOP_CRY))
4719 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4722 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4727 emitcode ("clr", "c");
4732 if (AOP_TYPE (right) == AOP_CRY)
4735 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4741 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4743 emitcode ("rrc", "a");
4744 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4752 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4753 genIfxJump (ifx, "c");
4757 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4758 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4759 if ((AOP_TYPE (right) == AOP_LIT) &&
4760 (AOP_TYPE (result) == AOP_CRY) &&
4761 (AOP_TYPE (left) != AOP_CRY))
4763 int posbit = isLiteralBit (lit);
4768 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4771 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4777 sprintf (buffer, "acc.%d", posbit & 0x07);
4778 genIfxJump (ifx, buffer);
4785 symbol *tlbl = newiTempLabel (NULL);
4786 int sizel = AOP_SIZE (left);
4788 emitcode ("setb", "c");
4791 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4793 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4795 if ((posbit = isLiteralBit (bytelit)) != 0)
4796 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4799 if (bytelit != 0x0FFL)
4800 emitcode ("anl", "a,%s",
4801 aopGet (AOP (right), offset, FALSE, TRUE));
4802 emitcode ("jnz", "%05d$", tlbl->key + 100);
4807 // bit = left & literal
4810 emitcode ("clr", "c");
4811 emitcode ("", "%05d$:", tlbl->key + 100);
4813 // if(left & literal)
4817 jmpTrueOrFalse (ifx, tlbl);
4825 /* if left is same as result */
4826 if (sameRegs (AOP (result), AOP (left)))
4828 for (; size--; offset++)
4830 if (AOP_TYPE (right) == AOP_LIT)
4832 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4834 else if (bytelit == 0)
4835 aopPut (AOP (result), zero, offset);
4836 else if (IS_AOP_PREG (result))
4838 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4839 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4840 aopPut (AOP (result), "a", offset);
4843 emitcode ("anl", "%s,%s",
4844 aopGet (AOP (left), offset, FALSE, TRUE),
4845 aopGet (AOP (right), offset, FALSE, FALSE));
4849 if (AOP_TYPE (left) == AOP_ACC)
4850 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4853 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4854 if (IS_AOP_PREG (result))
4856 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4857 aopPut (AOP (result), "a", offset);
4861 emitcode ("anl", "%s,a",
4862 aopGet (AOP (left), offset, FALSE, TRUE));
4869 // left & result in different registers
4870 if (AOP_TYPE (result) == AOP_CRY)
4873 // if(size), result in bit
4874 // if(!size && ifx), conditional oper: if(left & right)
4875 symbol *tlbl = newiTempLabel (NULL);
4876 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4878 emitcode ("setb", "c");
4881 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4882 emitcode ("anl", "a,%s",
4883 aopGet (AOP (right), offset, FALSE, FALSE));
4885 if (AOP_TYPE(left)==AOP_ACC) {
4886 emitcode("mov", "b,a");
4887 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4888 emitcode("anl", "a,b");
4890 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4891 emitcode ("anl", "a,%s",
4892 aopGet (AOP (left), offset, FALSE, FALSE));
4895 emitcode ("jnz", "%05d$", tlbl->key + 100);
4901 emitcode ("", "%05d$:", tlbl->key + 100);
4905 jmpTrueOrFalse (ifx, tlbl);
4909 for (; (size--); offset++)
4912 // result = left & right
4913 if (AOP_TYPE (right) == AOP_LIT)
4915 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4917 aopPut (AOP (result),
4918 aopGet (AOP (left), offset, FALSE, FALSE),
4922 else if (bytelit == 0)
4924 aopPut (AOP (result), zero, offset);
4928 // faster than result <- left, anl result,right
4929 // and better if result is SFR
4930 if (AOP_TYPE (left) == AOP_ACC)
4931 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4935 emitcode ("anl", "a,%s",
4936 aopGet (AOP (left), offset, FALSE, FALSE));
4938 aopPut (AOP (result), "a", offset);
4944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 freeAsmop (result, NULL, ic, TRUE);
4949 /*-----------------------------------------------------------------*/
4950 /* genOr - code for or */
4951 /*-----------------------------------------------------------------*/
4953 genOr (iCode * ic, iCode * ifx)
4955 operand *left, *right, *result;
4956 int size, offset = 0;
4957 unsigned long lit = 0L;
4959 D(emitcode ("; genOr",""));
4961 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4962 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4963 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4966 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4968 AOP_TYPE (left), AOP_TYPE (right));
4969 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4971 AOP_SIZE (left), AOP_SIZE (right));
4974 /* if left is a literal & right is not then exchange them */
4975 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4976 AOP_NEEDSACC (left))
4978 operand *tmp = right;
4983 /* if result = right then exchange them */
4984 if (sameRegs (AOP (result), AOP (right)))
4986 operand *tmp = right;
4991 /* if right is bit then exchange them */
4992 if (AOP_TYPE (right) == AOP_CRY &&
4993 AOP_TYPE (left) != AOP_CRY)
4995 operand *tmp = right;
4999 if (AOP_TYPE (right) == AOP_LIT)
5000 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5002 size = AOP_SIZE (result);
5006 if (AOP_TYPE (left) == AOP_CRY)
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 // c = bit | literal;
5013 // lit != 0 => result = 1
5014 if (AOP_TYPE (result) == AOP_CRY)
5017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5019 continueIfTrue (ifx);
5022 emitcode ("setb", "c");
5026 // lit == 0 => result = left
5027 if (size && sameRegs (AOP (result), AOP (left)))
5029 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5034 if (AOP_TYPE (right) == AOP_CRY)
5037 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5038 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5043 symbol *tlbl = newiTempLabel (NULL);
5044 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5045 emitcode ("setb", "c");
5046 emitcode ("jb", "%s,%05d$",
5047 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5049 emitcode ("jnz", "%05d$", tlbl->key + 100);
5050 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5052 jmpTrueOrFalse (ifx, tlbl);
5058 emitcode ("", "%05d$:", tlbl->key + 100);
5067 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5068 genIfxJump (ifx, "c");
5072 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5073 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5074 if ((AOP_TYPE (right) == AOP_LIT) &&
5075 (AOP_TYPE (result) == AOP_CRY) &&
5076 (AOP_TYPE (left) != AOP_CRY))
5082 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5084 continueIfTrue (ifx);
5089 // lit = 0, result = boolean(left)
5091 emitcode ("setb", "c");
5095 symbol *tlbl = newiTempLabel (NULL);
5096 emitcode ("jnz", "%05d$", tlbl->key + 100);
5098 emitcode ("", "%05d$:", tlbl->key + 100);
5102 genIfxJump (ifx, "a");
5110 /* if left is same as result */
5111 if (sameRegs (AOP (result), AOP (left)))
5113 for (; size--; offset++)
5115 if (AOP_TYPE (right) == AOP_LIT)
5117 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5119 else if (IS_AOP_PREG (left))
5121 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5122 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5123 aopPut (AOP (result), "a", offset);
5126 emitcode ("orl", "%s,%s",
5127 aopGet (AOP (left), offset, FALSE, TRUE),
5128 aopGet (AOP (right), offset, FALSE, FALSE));
5132 if (AOP_TYPE (left) == AOP_ACC)
5133 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5136 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5137 if (IS_AOP_PREG (left))
5139 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5140 aopPut (AOP (result), "a", offset);
5143 emitcode ("orl", "%s,a",
5144 aopGet (AOP (left), offset, FALSE, TRUE));
5151 // left & result in different registers
5152 if (AOP_TYPE (result) == AOP_CRY)
5155 // if(size), result in bit
5156 // if(!size && ifx), conditional oper: if(left | right)
5157 symbol *tlbl = newiTempLabel (NULL);
5158 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5160 emitcode ("setb", "c");
5163 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5164 emitcode ("orl", "a,%s",
5165 aopGet (AOP (right), offset, FALSE, FALSE));
5167 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5168 emitcode ("orl", "a,%s",
5169 aopGet (AOP (left), offset, FALSE, FALSE));
5171 emitcode ("jnz", "%05d$", tlbl->key + 100);
5177 emitcode ("", "%05d$:", tlbl->key + 100);
5181 jmpTrueOrFalse (ifx, tlbl);
5184 for (; (size--); offset++)
5187 // result = left & right
5188 if (AOP_TYPE (right) == AOP_LIT)
5190 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5192 aopPut (AOP (result),
5193 aopGet (AOP (left), offset, FALSE, FALSE),
5198 // faster than result <- left, anl result,right
5199 // and better if result is SFR
5200 if (AOP_TYPE (left) == AOP_ACC)
5201 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5204 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5205 emitcode ("orl", "a,%s",
5206 aopGet (AOP (left), offset, FALSE, FALSE));
5208 aopPut (AOP (result), "a", offset);
5213 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5215 freeAsmop (result, NULL, ic, TRUE);
5218 /*-----------------------------------------------------------------*/
5219 /* genXor - code for xclusive or */
5220 /*-----------------------------------------------------------------*/
5222 genXor (iCode * ic, iCode * ifx)
5224 operand *left, *right, *result;
5225 int size, offset = 0;
5226 unsigned long lit = 0L;
5228 D(emitcode ("; genXor",""));
5230 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5231 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5232 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5235 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5237 AOP_TYPE (left), AOP_TYPE (right));
5238 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5240 AOP_SIZE (left), AOP_SIZE (right));
5243 /* if left is a literal & right is not ||
5244 if left needs acc & right does not */
5245 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5246 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5248 operand *tmp = right;
5253 /* if result = right then exchange them */
5254 if (sameRegs (AOP (result), AOP (right)))
5256 operand *tmp = right;
5261 /* if right is bit then exchange them */
5262 if (AOP_TYPE (right) == AOP_CRY &&
5263 AOP_TYPE (left) != AOP_CRY)
5265 operand *tmp = right;
5269 if (AOP_TYPE (right) == AOP_LIT)
5270 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5272 size = AOP_SIZE (result);
5276 if (AOP_TYPE (left) == AOP_CRY)
5278 if (AOP_TYPE (right) == AOP_LIT)
5280 // c = bit & literal;
5283 // lit>>1 != 0 => result = 1
5284 if (AOP_TYPE (result) == AOP_CRY)
5287 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5289 continueIfTrue (ifx);
5292 emitcode ("setb", "c");
5299 // lit == 0, result = left
5300 if (size && sameRegs (AOP (result), AOP (left)))
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5306 // lit == 1, result = not(left)
5307 if (size && sameRegs (AOP (result), AOP (left)))
5309 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5314 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5315 emitcode ("cpl", "c");
5324 symbol *tlbl = newiTempLabel (NULL);
5325 if (AOP_TYPE (right) == AOP_CRY)
5328 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5332 int sizer = AOP_SIZE (right);
5334 // if val>>1 != 0, result = 1
5335 emitcode ("setb", "c");
5338 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5340 // test the msb of the lsb
5341 emitcode ("anl", "a,#0xfe");
5342 emitcode ("jnz", "%05d$", tlbl->key + 100);
5346 emitcode ("rrc", "a");
5348 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5349 emitcode ("cpl", "c");
5350 emitcode ("", "%05d$:", (tlbl->key + 100));
5357 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5358 genIfxJump (ifx, "c");
5362 if (sameRegs (AOP (result), AOP (left)))
5364 /* if left is same as result */
5365 for (; size--; offset++)
5367 if (AOP_TYPE (right) == AOP_LIT)
5369 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5371 else if (IS_AOP_PREG (left))
5373 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5374 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5375 aopPut (AOP (result), "a", offset);
5378 emitcode ("xrl", "%s,%s",
5379 aopGet (AOP (left), offset, FALSE, TRUE),
5380 aopGet (AOP (right), offset, FALSE, FALSE));
5384 if (AOP_TYPE (left) == AOP_ACC)
5385 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5389 if (IS_AOP_PREG (left))
5391 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5392 aopPut (AOP (result), "a", offset);
5395 emitcode ("xrl", "%s,a",
5396 aopGet (AOP (left), offset, FALSE, TRUE));
5403 // left & result in different registers
5404 if (AOP_TYPE (result) == AOP_CRY)
5407 // if(size), result in bit
5408 // if(!size && ifx), conditional oper: if(left ^ right)
5409 symbol *tlbl = newiTempLabel (NULL);
5410 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5412 emitcode ("setb", "c");
5415 if ((AOP_TYPE (right) == AOP_LIT) &&
5416 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5418 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5422 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5423 emitcode ("xrl", "a,%s",
5424 aopGet (AOP (right), offset, FALSE, FALSE));
5426 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5427 emitcode ("xrl", "a,%s",
5428 aopGet (AOP (left), offset, FALSE, FALSE));
5431 emitcode ("jnz", "%05d$", tlbl->key + 100);
5437 emitcode ("", "%05d$:", tlbl->key + 100);
5441 jmpTrueOrFalse (ifx, tlbl);
5444 for (; (size--); offset++)
5447 // result = left & right
5448 if (AOP_TYPE (right) == AOP_LIT)
5450 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5452 aopPut (AOP (result),
5453 aopGet (AOP (left), offset, FALSE, FALSE),
5458 // faster than result <- left, anl result,right
5459 // and better if result is SFR
5460 if (AOP_TYPE (left) == AOP_ACC)
5461 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5464 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5465 emitcode ("xrl", "a,%s",
5466 aopGet (AOP (left), offset, FALSE, TRUE));
5468 aopPut (AOP (result), "a", offset);
5473 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5474 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5475 freeAsmop (result, NULL, ic, TRUE);
5478 /*-----------------------------------------------------------------*/
5479 /* genInline - write the inline code out */
5480 /*-----------------------------------------------------------------*/
5482 genInline (iCode * ic)
5484 char *buffer, *bp, *bp1;
5486 D(emitcode ("; genInline",""));
5488 _G.inLine += (!options.asmpeep);
5490 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5491 strcpy (buffer, IC_INLINE (ic));
5493 /* emit each line as a code */
5518 /* emitcode("",buffer); */
5519 _G.inLine -= (!options.asmpeep);
5522 /*-----------------------------------------------------------------*/
5523 /* genRRC - rotate right with carry */
5524 /*-----------------------------------------------------------------*/
5528 operand *left, *result;
5529 int size, offset = 0;
5532 D(emitcode ("; genRRC",""));
5534 /* rotate right with carry */
5535 left = IC_LEFT (ic);
5536 result = IC_RESULT (ic);
5537 aopOp (left, ic, FALSE);
5538 aopOp (result, ic, FALSE);
5540 /* move it to the result */
5541 size = AOP_SIZE (result);
5543 if (size == 1) { /* special case for 1 byte */
5544 l = aopGet (AOP (left), offset, FALSE, FALSE);
5546 emitcode ("rr", "a");
5552 l = aopGet (AOP (left), offset, FALSE, FALSE);
5554 emitcode ("rrc", "a");
5555 if (AOP_SIZE (result) > 1)
5556 aopPut (AOP (result), "a", offset--);
5558 /* now we need to put the carry into the
5559 highest order byte of the result */
5560 if (AOP_SIZE (result) > 1)
5562 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5565 emitcode ("mov", "acc.7,c");
5567 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5568 freeAsmop (left, NULL, ic, TRUE);
5569 freeAsmop (result, NULL, ic, TRUE);
5572 /*-----------------------------------------------------------------*/
5573 /* genRLC - generate code for rotate left with carry */
5574 /*-----------------------------------------------------------------*/
5578 operand *left, *result;
5579 int size, offset = 0;
5582 D(emitcode ("; genRLC",""));
5584 /* rotate right with carry */
5585 left = IC_LEFT (ic);
5586 result = IC_RESULT (ic);
5587 aopOp (left, ic, FALSE);
5588 aopOp (result, ic, FALSE);
5590 /* move it to the result */
5591 size = AOP_SIZE (result);
5595 l = aopGet (AOP (left), offset, FALSE, FALSE);
5597 if (size == 0) { /* special case for 1 byte */
5601 emitcode ("add", "a,acc");
5602 if (AOP_SIZE (result) > 1)
5603 aopPut (AOP (result), "a", offset++);
5606 l = aopGet (AOP (left), offset, FALSE, FALSE);
5608 emitcode ("rlc", "a");
5609 if (AOP_SIZE (result) > 1)
5610 aopPut (AOP (result), "a", offset++);
5613 /* now we need to put the carry into the
5614 highest order byte of the result */
5615 if (AOP_SIZE (result) > 1)
5617 l = aopGet (AOP (result), 0, FALSE, FALSE);
5620 emitcode ("mov", "acc.0,c");
5622 aopPut (AOP (result), "a", 0);
5623 freeAsmop (left, NULL, ic, TRUE);
5624 freeAsmop (result, NULL, ic, TRUE);
5627 /*-----------------------------------------------------------------*/
5628 /* genGetHbit - generates code get highest order bit */
5629 /*-----------------------------------------------------------------*/
5631 genGetHbit (iCode * ic)
5633 operand *left, *result;
5635 D(emitcode ("; genGetHbit",""));
5637 left = IC_LEFT (ic);
5638 result = IC_RESULT (ic);
5639 aopOp (left, ic, FALSE);
5640 aopOp (result, ic, FALSE);
5642 /* get the highest order byte into a */
5643 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5644 if (AOP_TYPE (result) == AOP_CRY)
5646 emitcode ("rlc", "a");
5651 emitcode ("rl", "a");
5652 emitcode ("anl", "a,#0x01");
5657 freeAsmop (left, NULL, ic, TRUE);
5658 freeAsmop (result, NULL, ic, TRUE);
5661 /*-----------------------------------------------------------------*/
5662 /* AccRol - rotate left accumulator by known count */
5663 /*-----------------------------------------------------------------*/
5665 AccRol (int shCount)
5667 shCount &= 0x0007; // shCount : 0..7
5674 emitcode ("rl", "a");
5677 emitcode ("rl", "a");
5678 emitcode ("rl", "a");
5681 emitcode ("swap", "a");
5682 emitcode ("rr", "a");
5685 emitcode ("swap", "a");
5688 emitcode ("swap", "a");
5689 emitcode ("rl", "a");
5692 emitcode ("rr", "a");
5693 emitcode ("rr", "a");
5696 emitcode ("rr", "a");
5701 /*-----------------------------------------------------------------*/
5702 /* AccLsh - left shift accumulator by known count */
5703 /*-----------------------------------------------------------------*/
5705 AccLsh (int shCount)
5710 emitcode ("add", "a,acc");
5711 else if (shCount == 2)
5713 emitcode ("add", "a,acc");
5714 emitcode ("add", "a,acc");
5718 /* rotate left accumulator */
5720 /* and kill the lower order bits */
5721 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5726 /*-----------------------------------------------------------------*/
5727 /* AccRsh - right shift accumulator by known count */
5728 /*-----------------------------------------------------------------*/
5730 AccRsh (int shCount)
5737 emitcode ("rrc", "a");
5741 /* rotate right accumulator */
5742 AccRol (8 - shCount);
5743 /* and kill the higher order bits */
5744 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5749 /*-----------------------------------------------------------------*/
5750 /* AccSRsh - signed right shift accumulator by known count */
5751 /*-----------------------------------------------------------------*/
5753 AccSRsh (int shCount)
5760 emitcode ("mov", "c,acc.7");
5761 emitcode ("rrc", "a");
5763 else if (shCount == 2)
5765 emitcode ("mov", "c,acc.7");
5766 emitcode ("rrc", "a");
5767 emitcode ("mov", "c,acc.7");
5768 emitcode ("rrc", "a");
5772 tlbl = newiTempLabel (NULL);
5773 /* rotate right accumulator */
5774 AccRol (8 - shCount);
5775 /* and kill the higher order bits */
5776 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5777 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5778 emitcode ("orl", "a,#0x%02x",
5779 (unsigned char) ~SRMask[shCount]);
5780 emitcode ("", "%05d$:", tlbl->key + 100);
5785 /*-----------------------------------------------------------------*/
5786 /* shiftR1Left2Result - shift right one byte from left to result */
5787 /*-----------------------------------------------------------------*/
5789 shiftR1Left2Result (operand * left, int offl,
5790 operand * result, int offr,
5791 int shCount, int sign)
5793 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5794 /* shift right accumulator */
5799 aopPut (AOP (result), "a", offr);
5802 /*-----------------------------------------------------------------*/
5803 /* shiftL1Left2Result - shift left one byte from left to result */
5804 /*-----------------------------------------------------------------*/
5806 shiftL1Left2Result (operand * left, int offl,
5807 operand * result, int offr, int shCount)
5810 l = aopGet (AOP (left), offl, FALSE, FALSE);
5812 /* shift left accumulator */
5814 aopPut (AOP (result), "a", offr);
5817 /*-----------------------------------------------------------------*/
5818 /* movLeft2Result - move byte from left to result */
5819 /*-----------------------------------------------------------------*/
5821 movLeft2Result (operand * left, int offl,
5822 operand * result, int offr, int sign)
5825 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5827 l = aopGet (AOP (left), offl, FALSE, FALSE);
5829 if (*l == '@' && (IS_AOP_PREG (result)))
5831 emitcode ("mov", "a,%s", l);
5832 aopPut (AOP (result), "a", offr);
5837 aopPut (AOP (result), l, offr);
5840 /* MSB sign in acc.7 ! */
5841 if (getDataSize (left) == offl + 1)
5843 emitcode ("mov", "a,%s", l);
5844 aopPut (AOP (result), "a", offr);
5851 /*-----------------------------------------------------------------*/
5852 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5853 /*-----------------------------------------------------------------*/
5857 emitcode ("rrc", "a");
5858 emitcode ("xch", "a,%s", x);
5859 emitcode ("rrc", "a");
5860 emitcode ("xch", "a,%s", x);
5863 /*-----------------------------------------------------------------*/
5864 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5865 /*-----------------------------------------------------------------*/
5869 emitcode ("xch", "a,%s", x);
5870 emitcode ("rlc", "a");
5871 emitcode ("xch", "a,%s", x);
5872 emitcode ("rlc", "a");
5875 /*-----------------------------------------------------------------*/
5876 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5877 /*-----------------------------------------------------------------*/
5881 emitcode ("xch", "a,%s", x);
5882 emitcode ("add", "a,acc");
5883 emitcode ("xch", "a,%s", x);
5884 emitcode ("rlc", "a");
5887 /*-----------------------------------------------------------------*/
5888 /* AccAXLsh - left shift a:x by known count (0..7) */
5889 /*-----------------------------------------------------------------*/
5891 AccAXLsh (char *x, int shCount)
5906 case 5: // AAAAABBB:CCCCCDDD
5908 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5910 emitcode ("anl", "a,#0x%02x",
5911 SLMask[shCount]); // BBB00000:CCCCCDDD
5913 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5915 AccRol (shCount); // DDDCCCCC:BBB00000
5917 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5919 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5921 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5923 emitcode ("anl", "a,#0x%02x",
5924 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5926 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5928 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5931 case 6: // AAAAAABB:CCCCCCDD
5932 emitcode ("anl", "a,#0x%02x",
5933 SRMask[shCount]); // 000000BB:CCCCCCDD
5934 emitcode ("mov", "c,acc.0"); // c = B
5935 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5937 AccAXRrl1 (x); // BCCCCCCD:D000000B
5938 AccAXRrl1 (x); // BBCCCCCC:DD000000
5940 emitcode("rrc","a");
5941 emitcode("xch","a,%s", x);
5942 emitcode("rrc","a");
5943 emitcode("mov","c,acc.0"); //<< get correct bit
5944 emitcode("xch","a,%s", x);
5946 emitcode("rrc","a");
5947 emitcode("xch","a,%s", x);
5948 emitcode("rrc","a");
5949 emitcode("xch","a,%s", x);
5952 case 7: // a:x <<= 7
5954 emitcode ("anl", "a,#0x%02x",
5955 SRMask[shCount]); // 0000000B:CCCCCCCD
5957 emitcode ("mov", "c,acc.0"); // c = B
5959 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5961 AccAXRrl1 (x); // BCCCCCCC:D0000000
5969 /*-----------------------------------------------------------------*/
5970 /* AccAXRsh - right shift a:x known count (0..7) */
5971 /*-----------------------------------------------------------------*/
5973 AccAXRsh (char *x, int shCount)
5981 AccAXRrl1 (x); // 0->a:x
5986 AccAXRrl1 (x); // 0->a:x
5989 AccAXRrl1 (x); // 0->a:x
5994 case 5: // AAAAABBB:CCCCCDDD = a:x
5996 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5998 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6000 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6002 emitcode ("anl", "a,#0x%02x",
6003 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6005 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6007 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6009 emitcode ("anl", "a,#0x%02x",
6010 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6012 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6014 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6016 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6019 case 6: // AABBBBBB:CCDDDDDD
6021 emitcode ("mov", "c,acc.7");
6022 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6024 emitcode ("mov", "c,acc.7");
6025 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6027 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6029 emitcode ("anl", "a,#0x%02x",
6030 SRMask[shCount]); // 000000AA:BBBBBBCC
6033 case 7: // ABBBBBBB:CDDDDDDD
6035 emitcode ("mov", "c,acc.7"); // c = A
6037 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6039 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6041 emitcode ("anl", "a,#0x%02x",
6042 SRMask[shCount]); // 0000000A:BBBBBBBC
6050 /*-----------------------------------------------------------------*/
6051 /* AccAXRshS - right shift signed a:x known count (0..7) */
6052 /*-----------------------------------------------------------------*/
6054 AccAXRshS (char *x, int shCount)
6062 emitcode ("mov", "c,acc.7");
6063 AccAXRrl1 (x); // s->a:x
6067 emitcode ("mov", "c,acc.7");
6068 AccAXRrl1 (x); // s->a:x
6070 emitcode ("mov", "c,acc.7");
6071 AccAXRrl1 (x); // s->a:x
6076 case 5: // AAAAABBB:CCCCCDDD = a:x
6078 tlbl = newiTempLabel (NULL);
6079 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6081 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6083 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6085 emitcode ("anl", "a,#0x%02x",
6086 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6088 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6090 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6092 emitcode ("anl", "a,#0x%02x",
6093 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6095 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6097 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6099 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6101 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6102 emitcode ("orl", "a,#0x%02x",
6103 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6105 emitcode ("", "%05d$:", tlbl->key + 100);
6106 break; // SSSSAAAA:BBBCCCCC
6108 case 6: // AABBBBBB:CCDDDDDD
6110 tlbl = newiTempLabel (NULL);
6111 emitcode ("mov", "c,acc.7");
6112 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6114 emitcode ("mov", "c,acc.7");
6115 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6117 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6119 emitcode ("anl", "a,#0x%02x",
6120 SRMask[shCount]); // 000000AA:BBBBBBCC
6122 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6123 emitcode ("orl", "a,#0x%02x",
6124 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6126 emitcode ("", "%05d$:", tlbl->key + 100);
6128 case 7: // ABBBBBBB:CDDDDDDD
6130 tlbl = newiTempLabel (NULL);
6131 emitcode ("mov", "c,acc.7"); // c = A
6133 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6135 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6137 emitcode ("anl", "a,#0x%02x",
6138 SRMask[shCount]); // 0000000A:BBBBBBBC
6140 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6141 emitcode ("orl", "a,#0x%02x",
6142 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6144 emitcode ("", "%05d$:", tlbl->key + 100);
6151 /*-----------------------------------------------------------------*/
6152 /* shiftL2Left2Result - shift left two bytes from left to result */
6153 /*-----------------------------------------------------------------*/
6155 shiftL2Left2Result (operand * left, int offl,
6156 operand * result, int offr, int shCount)
6158 if (sameRegs (AOP (result), AOP (left)) &&
6159 ((offl + MSB16) == offr))
6161 /* don't crash result[offr] */
6162 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6163 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6167 movLeft2Result (left, offl, result, offr, 0);
6168 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6170 /* ax << shCount (x = lsb(result)) */
6171 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6172 aopPut (AOP (result), "a", offr + MSB16);
6176 /*-----------------------------------------------------------------*/
6177 /* shiftR2Left2Result - shift right two bytes from left to result */
6178 /*-----------------------------------------------------------------*/
6180 shiftR2Left2Result (operand * left, int offl,
6181 operand * result, int offr,
6182 int shCount, int sign)
6184 if (sameRegs (AOP (result), AOP (left)) &&
6185 ((offl + MSB16) == offr))
6187 /* don't crash result[offr] */
6188 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6189 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6193 movLeft2Result (left, offl, result, offr, 0);
6194 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6196 /* a:x >> shCount (x = lsb(result)) */
6198 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6200 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6201 if (getDataSize (result) > 1)
6202 aopPut (AOP (result), "a", offr + MSB16);
6205 /*-----------------------------------------------------------------*/
6206 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6207 /*-----------------------------------------------------------------*/
6209 shiftLLeftOrResult (operand * left, int offl,
6210 operand * result, int offr, int shCount)
6212 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6213 /* shift left accumulator */
6215 /* or with result */
6216 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6217 /* back to result */
6218 aopPut (AOP (result), "a", offr);
6221 /*-----------------------------------------------------------------*/
6222 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6223 /*-----------------------------------------------------------------*/
6225 shiftRLeftOrResult (operand * left, int offl,
6226 operand * result, int offr, int shCount)
6228 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6229 /* shift right accumulator */
6231 /* or with result */
6232 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6233 /* back to result */
6234 aopPut (AOP (result), "a", offr);
6237 /*-----------------------------------------------------------------*/
6238 /* genlshOne - left shift a one byte quantity by known count */
6239 /*-----------------------------------------------------------------*/
6241 genlshOne (operand * result, operand * left, int shCount)
6243 D(emitcode ("; genlshOne",""));
6245 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6248 /*-----------------------------------------------------------------*/
6249 /* genlshTwo - left shift two bytes by known amount != 0 */
6250 /*-----------------------------------------------------------------*/
6252 genlshTwo (operand * result, operand * left, int shCount)
6256 D(emitcode ("; genlshTwo",""));
6258 size = getDataSize (result);
6260 /* if shCount >= 8 */
6268 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6270 movLeft2Result (left, LSB, result, MSB16, 0);
6272 aopPut (AOP (result), zero, LSB);
6275 /* 1 <= shCount <= 7 */
6279 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6281 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6285 /*-----------------------------------------------------------------*/
6286 /* shiftLLong - shift left one long from left to result */
6287 /* offl = LSB or MSB16 */
6288 /*-----------------------------------------------------------------*/
6290 shiftLLong (operand * left, operand * result, int offr)
6293 int size = AOP_SIZE (result);
6295 if (size >= LSB + offr)
6297 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6299 emitcode ("add", "a,acc");
6300 if (sameRegs (AOP (left), AOP (result)) &&
6301 size >= MSB16 + offr && offr != LSB)
6302 emitcode ("xch", "a,%s",
6303 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6305 aopPut (AOP (result), "a", LSB + offr);
6308 if (size >= MSB16 + offr)
6310 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6312 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6315 emitcode ("rlc", "a");
6316 if (sameRegs (AOP (left), AOP (result)) &&
6317 size >= MSB24 + offr && offr != LSB)
6318 emitcode ("xch", "a,%s",
6319 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6321 aopPut (AOP (result), "a", MSB16 + offr);
6324 if (size >= MSB24 + offr)
6326 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6328 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6331 emitcode ("rlc", "a");
6332 if (sameRegs (AOP (left), AOP (result)) &&
6333 size >= MSB32 + offr && offr != LSB)
6334 emitcode ("xch", "a,%s",
6335 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6337 aopPut (AOP (result), "a", MSB24 + offr);
6340 if (size > MSB32 + offr)
6342 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6344 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6347 emitcode ("rlc", "a");
6348 aopPut (AOP (result), "a", MSB32 + offr);
6351 aopPut (AOP (result), zero, LSB);
6354 /*-----------------------------------------------------------------*/
6355 /* genlshFour - shift four byte by a known amount != 0 */
6356 /*-----------------------------------------------------------------*/
6358 genlshFour (operand * result, operand * left, int shCount)
6362 D(emitcode ("; genlshFour",""));
6364 size = AOP_SIZE (result);
6366 /* if shifting more that 3 bytes */
6371 /* lowest order of left goes to the highest
6372 order of the destination */
6373 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6375 movLeft2Result (left, LSB, result, MSB32, 0);
6376 aopPut (AOP (result), zero, LSB);
6377 aopPut (AOP (result), zero, MSB16);
6378 aopPut (AOP (result), zero, MSB24);
6382 /* more than two bytes */
6383 else if (shCount >= 16)
6385 /* lower order two bytes goes to higher order two bytes */
6387 /* if some more remaining */
6389 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6392 movLeft2Result (left, MSB16, result, MSB32, 0);
6393 movLeft2Result (left, LSB, result, MSB24, 0);
6395 aopPut (AOP (result), zero, MSB16);
6396 aopPut (AOP (result), zero, LSB);
6400 /* if more than 1 byte */
6401 else if (shCount >= 8)
6403 /* lower order three bytes goes to higher order three bytes */
6408 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6410 movLeft2Result (left, LSB, result, MSB16, 0);
6416 movLeft2Result (left, MSB24, result, MSB32, 0);
6417 movLeft2Result (left, MSB16, result, MSB24, 0);
6418 movLeft2Result (left, LSB, result, MSB16, 0);
6419 aopPut (AOP (result), zero, LSB);
6421 else if (shCount == 1)
6422 shiftLLong (left, result, MSB16);
6425 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6426 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6427 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6428 aopPut (AOP (result), zero, LSB);
6433 /* 1 <= shCount <= 7 */
6434 else if (shCount <= 2)
6436 shiftLLong (left, result, LSB);
6438 shiftLLong (result, result, LSB);
6440 /* 3 <= shCount <= 7, optimize */
6443 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6444 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6445 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6449 /*-----------------------------------------------------------------*/
6450 /* genLeftShiftLiteral - left shifting by known count */
6451 /*-----------------------------------------------------------------*/
6453 genLeftShiftLiteral (operand * left,
6458 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6461 D(emitcode ("; genLeftShiftLiteral",""));
6463 freeAsmop (right, NULL, ic, TRUE);
6465 aopOp (left, ic, FALSE);
6466 aopOp (result, ic, FALSE);
6468 size = getSize (operandType (result));
6471 emitcode ("; shift left ", "result %d, left %d", size,
6475 /* I suppose that the left size >= result size */
6480 movLeft2Result (left, size, result, size, 0);
6484 else if (shCount >= (size * 8))
6486 aopPut (AOP (result), zero, size);
6492 genlshOne (result, left, shCount);
6496 genlshTwo (result, left, shCount);
6500 genlshFour (result, left, shCount);
6503 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6504 "*** ack! mystery literal shift!\n");
6508 freeAsmop (left, NULL, ic, TRUE);
6509 freeAsmop (result, NULL, ic, TRUE);
6512 /*-----------------------------------------------------------------*/
6513 /* genLeftShift - generates code for left shifting */
6514 /*-----------------------------------------------------------------*/
6516 genLeftShift (iCode * ic)
6518 operand *left, *right, *result;
6521 symbol *tlbl, *tlbl1;
6523 D(emitcode ("; genLeftShift",""));
6525 right = IC_RIGHT (ic);
6526 left = IC_LEFT (ic);
6527 result = IC_RESULT (ic);
6529 aopOp (right, ic, FALSE);
6531 /* if the shift count is known then do it
6532 as efficiently as possible */
6533 if (AOP_TYPE (right) == AOP_LIT)
6535 genLeftShiftLiteral (left, right, result, ic);
6539 /* shift count is unknown then we have to form
6540 a loop get the loop count in B : Note: we take
6541 only the lower order byte since shifting
6542 more that 32 bits make no sense anyway, ( the
6543 largest size of an object can be only 32 bits ) */
6545 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6546 emitcode ("inc", "b");
6547 freeAsmop (right, NULL, ic, TRUE);
6548 aopOp (left, ic, FALSE);
6549 aopOp (result, ic, FALSE);
6551 /* now move the left to the result if they are not the
6553 if (!sameRegs (AOP (left), AOP (result)) &&
6554 AOP_SIZE (result) > 1)
6557 size = AOP_SIZE (result);
6561 l = aopGet (AOP (left), offset, FALSE, TRUE);
6562 if (*l == '@' && (IS_AOP_PREG (result)))
6565 emitcode ("mov", "a,%s", l);
6566 aopPut (AOP (result), "a", offset);
6569 aopPut (AOP (result), l, offset);
6574 tlbl = newiTempLabel (NULL);
6575 size = AOP_SIZE (result);
6577 tlbl1 = newiTempLabel (NULL);
6579 /* if it is only one byte then */
6582 symbol *tlbl1 = newiTempLabel (NULL);
6584 l = aopGet (AOP (left), 0, FALSE, FALSE);
6586 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6587 emitcode ("", "%05d$:", tlbl->key + 100);
6588 emitcode ("add", "a,acc");
6589 emitcode ("", "%05d$:", tlbl1->key + 100);
6590 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6591 aopPut (AOP (result), "a", 0);
6595 reAdjustPreg (AOP (result));
6597 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6598 emitcode ("", "%05d$:", tlbl->key + 100);
6599 l = aopGet (AOP (result), offset, FALSE, FALSE);
6601 emitcode ("add", "a,acc");
6602 aopPut (AOP (result), "a", offset++);
6605 l = aopGet (AOP (result), offset, FALSE, FALSE);
6607 emitcode ("rlc", "a");
6608 aopPut (AOP (result), "a", offset++);
6610 reAdjustPreg (AOP (result));
6612 emitcode ("", "%05d$:", tlbl1->key + 100);
6613 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6615 freeAsmop (left, NULL, ic, TRUE);
6616 freeAsmop (result, NULL, ic, TRUE);
6619 /*-----------------------------------------------------------------*/
6620 /* genrshOne - right shift a one byte quantity by known count */
6621 /*-----------------------------------------------------------------*/
6623 genrshOne (operand * result, operand * left,
6624 int shCount, int sign)
6626 D(emitcode ("; genrshOne",""));
6628 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6631 /*-----------------------------------------------------------------*/
6632 /* genrshTwo - right shift two bytes by known amount != 0 */
6633 /*-----------------------------------------------------------------*/
6635 genrshTwo (operand * result, operand * left,
6636 int shCount, int sign)
6638 D(emitcode ("; genrshTwo",""));
6640 /* if shCount >= 8 */
6645 shiftR1Left2Result (left, MSB16, result, LSB,
6648 movLeft2Result (left, MSB16, result, LSB, sign);
6649 addSign (result, MSB16, sign);
6652 /* 1 <= shCount <= 7 */
6654 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6657 /*-----------------------------------------------------------------*/
6658 /* shiftRLong - shift right one long from left to result */
6659 /* offl = LSB or MSB16 */
6660 /*-----------------------------------------------------------------*/
6662 shiftRLong (operand * left, int offl,
6663 operand * result, int sign)
6665 int isSameRegs=sameRegs(AOP(left),AOP(result));
6667 if (isSameRegs && offl>1) {
6668 // we are in big trouble, but this shouldn't happen
6669 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6672 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6677 emitcode ("rlc", "a");
6678 emitcode ("subb", "a,acc");
6680 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6682 aopPut (AOP (result), "a", MSB32);
6683 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6686 aopPut (AOP(result), zero, MSB32);
6691 emitcode ("clr", "c");
6693 emitcode ("mov", "c,acc.7");
6696 emitcode ("rrc", "a");
6698 if (isSameRegs && offl==MSB16) {
6699 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6701 aopPut (AOP (result), "a", MSB32-offl);
6702 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6705 emitcode ("rrc", "a");
6706 if (isSameRegs && offl==1) {
6707 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6709 aopPut (AOP (result), "a", MSB24-offl);
6710 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6712 emitcode ("rrc", "a");
6713 aopPut (AOP (result), "a", MSB16 - offl);
6717 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6718 emitcode ("rrc", "a");
6719 aopPut (AOP (result), "a", LSB);
6723 /*-----------------------------------------------------------------*/
6724 /* genrshFour - shift four byte by a known amount != 0 */
6725 /*-----------------------------------------------------------------*/
6727 genrshFour (operand * result, operand * left,
6728 int shCount, int sign)
6730 D(emitcode ("; genrshFour",""));
6732 /* if shifting more that 3 bytes */
6737 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6739 movLeft2Result (left, MSB32, result, LSB, sign);
6740 addSign (result, MSB16, sign);
6742 else if (shCount >= 16)
6746 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6749 movLeft2Result (left, MSB24, result, LSB, 0);
6750 movLeft2Result (left, MSB32, result, MSB16, sign);
6752 addSign (result, MSB24, sign);
6754 else if (shCount >= 8)
6758 shiftRLong (left, MSB16, result, sign);
6759 else if (shCount == 0)
6761 movLeft2Result (left, MSB16, result, LSB, 0);
6762 movLeft2Result (left, MSB24, result, MSB16, 0);
6763 movLeft2Result (left, MSB32, result, MSB24, sign);
6764 addSign (result, MSB32, sign);
6768 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6769 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6770 /* the last shift is signed */
6771 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6772 addSign (result, MSB32, sign);
6776 { /* 1 <= shCount <= 7 */
6779 shiftRLong (left, LSB, result, sign);
6781 shiftRLong (result, LSB, result, sign);
6785 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6786 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6787 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6792 /*-----------------------------------------------------------------*/
6793 /* genRightShiftLiteral - right shifting by known count */
6794 /*-----------------------------------------------------------------*/
6796 genRightShiftLiteral (operand * left,
6802 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6805 D(emitcode ("; genRightShiftLiteral",""));
6807 freeAsmop (right, NULL, ic, TRUE);
6809 aopOp (left, ic, FALSE);
6810 aopOp (result, ic, FALSE);
6813 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6817 size = getDataSize (left);
6818 /* test the LEFT size !!! */
6820 /* I suppose that the left size >= result size */
6823 size = getDataSize (result);
6825 movLeft2Result (left, size, result, size, 0);
6828 else if (shCount >= (size * 8))
6831 /* get sign in acc.7 */
6832 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6834 addSign (result, LSB, sign);
6841 genrshOne (result, left, shCount, sign);
6845 genrshTwo (result, left, shCount, sign);
6849 genrshFour (result, left, shCount, sign);
6855 freeAsmop (left, NULL, ic, TRUE);
6856 freeAsmop (result, NULL, ic, TRUE);
6859 /*-----------------------------------------------------------------*/
6860 /* genSignedRightShift - right shift of signed number */
6861 /*-----------------------------------------------------------------*/
6863 genSignedRightShift (iCode * ic)
6865 operand *right, *left, *result;
6868 symbol *tlbl, *tlbl1;
6870 D(emitcode ("; genSignedRightShift",""));
6872 /* we do it the hard way put the shift count in b
6873 and loop thru preserving the sign */
6875 right = IC_RIGHT (ic);
6876 left = IC_LEFT (ic);
6877 result = IC_RESULT (ic);
6879 aopOp (right, ic, FALSE);
6882 if (AOP_TYPE (right) == AOP_LIT)
6884 genRightShiftLiteral (left, right, result, ic, 1);
6887 /* shift count is unknown then we have to form
6888 a loop get the loop count in B : Note: we take
6889 only the lower order byte since shifting
6890 more that 32 bits make no sense anyway, ( the
6891 largest size of an object can be only 32 bits ) */
6893 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6894 emitcode ("inc", "b");
6895 freeAsmop (right, NULL, ic, TRUE);
6896 aopOp (left, ic, FALSE);
6897 aopOp (result, ic, FALSE);
6899 /* now move the left to the result if they are not the
6901 if (!sameRegs (AOP (left), AOP (result)) &&
6902 AOP_SIZE (result) > 1)
6905 size = AOP_SIZE (result);
6909 l = aopGet (AOP (left), offset, FALSE, TRUE);
6910 if (*l == '@' && IS_AOP_PREG (result))
6913 emitcode ("mov", "a,%s", l);
6914 aopPut (AOP (result), "a", offset);
6917 aopPut (AOP (result), l, offset);
6922 /* mov the highest order bit to OVR */
6923 tlbl = newiTempLabel (NULL);
6924 tlbl1 = newiTempLabel (NULL);
6926 size = AOP_SIZE (result);
6928 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6929 emitcode ("rlc", "a");
6930 emitcode ("mov", "ov,c");
6931 /* if it is only one byte then */
6934 l = aopGet (AOP (left), 0, FALSE, FALSE);
6936 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6937 emitcode ("", "%05d$:", tlbl->key + 100);
6938 emitcode ("mov", "c,ov");
6939 emitcode ("rrc", "a");
6940 emitcode ("", "%05d$:", tlbl1->key + 100);
6941 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6942 aopPut (AOP (result), "a", 0);
6946 reAdjustPreg (AOP (result));
6947 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6948 emitcode ("", "%05d$:", tlbl->key + 100);
6949 emitcode ("mov", "c,ov");
6952 l = aopGet (AOP (result), offset, FALSE, FALSE);
6954 emitcode ("rrc", "a");
6955 aopPut (AOP (result), "a", offset--);
6957 reAdjustPreg (AOP (result));
6958 emitcode ("", "%05d$:", tlbl1->key + 100);
6959 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6962 freeAsmop (left, NULL, ic, TRUE);
6963 freeAsmop (result, NULL, ic, TRUE);
6966 /*-----------------------------------------------------------------*/
6967 /* genRightShift - generate code for right shifting */
6968 /*-----------------------------------------------------------------*/
6970 genRightShift (iCode * ic)
6972 operand *right, *left, *result;
6976 symbol *tlbl, *tlbl1;
6978 D(emitcode ("; genRightShift",""));
6980 /* if signed then we do it the hard way preserve the
6981 sign bit moving it inwards */
6982 retype = getSpec (operandType (IC_RESULT (ic)));
6984 if (!SPEC_USIGN (retype))
6986 genSignedRightShift (ic);
6990 /* signed & unsigned types are treated the same : i.e. the
6991 signed is NOT propagated inwards : quoting from the
6992 ANSI - standard : "for E1 >> E2, is equivalent to division
6993 by 2**E2 if unsigned or if it has a non-negative value,
6994 otherwise the result is implementation defined ", MY definition
6995 is that the sign does not get propagated */
6997 right = IC_RIGHT (ic);
6998 left = IC_LEFT (ic);
6999 result = IC_RESULT (ic);
7001 aopOp (right, ic, FALSE);
7003 /* if the shift count is known then do it
7004 as efficiently as possible */
7005 if (AOP_TYPE (right) == AOP_LIT)
7007 genRightShiftLiteral (left, right, result, ic, 0);
7011 /* shift count is unknown then we have to form
7012 a loop get the loop count in B : Note: we take
7013 only the lower order byte since shifting
7014 more that 32 bits make no sense anyway, ( the
7015 largest size of an object can be only 32 bits ) */
7017 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7018 emitcode ("inc", "b");
7019 freeAsmop (right, NULL, ic, TRUE);
7020 aopOp (left, ic, FALSE);
7021 aopOp (result, ic, FALSE);
7023 /* now move the left to the result if they are not the
7025 if (!sameRegs (AOP (left), AOP (result)) &&
7026 AOP_SIZE (result) > 1)
7029 size = AOP_SIZE (result);
7033 l = aopGet (AOP (left), offset, FALSE, TRUE);
7034 if (*l == '@' && IS_AOP_PREG (result))
7037 emitcode ("mov", "a,%s", l);
7038 aopPut (AOP (result), "a", offset);
7041 aopPut (AOP (result), l, offset);
7046 tlbl = newiTempLabel (NULL);
7047 tlbl1 = newiTempLabel (NULL);
7048 size = AOP_SIZE (result);
7051 /* if it is only one byte then */
7054 l = aopGet (AOP (left), 0, FALSE, FALSE);
7056 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7057 emitcode ("", "%05d$:", tlbl->key + 100);
7059 emitcode ("rrc", "a");
7060 emitcode ("", "%05d$:", tlbl1->key + 100);
7061 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7062 aopPut (AOP (result), "a", 0);
7066 reAdjustPreg (AOP (result));
7067 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7068 emitcode ("", "%05d$:", tlbl->key + 100);
7072 l = aopGet (AOP (result), offset, FALSE, FALSE);
7074 emitcode ("rrc", "a");
7075 aopPut (AOP (result), "a", offset--);
7077 reAdjustPreg (AOP (result));
7079 emitcode ("", "%05d$:", tlbl1->key + 100);
7080 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7083 freeAsmop (left, NULL, ic, TRUE);
7084 freeAsmop (result, NULL, ic, TRUE);
7087 /*-----------------------------------------------------------------*/
7088 /* genUnpackBits - generates code for unpacking bits */
7089 /*-----------------------------------------------------------------*/
7091 genUnpackBits (operand * result, char *rname, int ptype)
7099 D(emitcode ("; genUnpackBits",""));
7101 etype = getSpec (operandType (result));
7102 rsize = getSize (operandType (result));
7103 /* read the first byte */
7109 emitcode ("mov", "a,@%s", rname);
7113 emitcode ("movx", "a,@%s", rname);
7117 emitcode ("movx", "a,@dptr");
7121 emitcode ("clr", "a");
7122 emitcode ("movc", "a,@a+dptr");
7126 emitcode ("lcall", "__gptrget");
7130 rlen = SPEC_BLEN (etype);
7132 /* if we have bitdisplacement then it fits */
7133 /* into this byte completely or if length is */
7134 /* less than a byte */
7135 if ((shCnt = SPEC_BSTR (etype)) ||
7136 (SPEC_BLEN (etype) <= 8))
7139 /* shift right acc */
7142 emitcode ("anl", "a,#0x%02x",
7143 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7144 aopPut (AOP (result), "a", offset++);
7148 /* bit field did not fit in a byte */
7149 aopPut (AOP (result), "a", offset++);
7158 emitcode ("inc", "%s", rname);
7159 emitcode ("mov", "a,@%s", rname);
7163 emitcode ("inc", "%s", rname);
7164 emitcode ("movx", "a,@%s", rname);
7168 emitcode ("inc", "dptr");
7169 emitcode ("movx", "a,@dptr");
7173 emitcode ("clr", "a");
7174 emitcode ("inc", "dptr");
7175 emitcode ("movc", "a,@a+dptr");
7179 emitcode ("inc", "dptr");
7180 emitcode ("lcall", "__gptrget");
7185 /* if we are done */
7189 aopPut (AOP (result), "a", offset++);
7195 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7197 aopPut (AOP (result), "a", offset++);
7205 aopPut (AOP (result), zero, offset++);
7211 /*-----------------------------------------------------------------*/
7212 /* genDataPointerGet - generates code when ptr offset is known */
7213 /*-----------------------------------------------------------------*/
7215 genDataPointerGet (operand * left,
7221 int size, offset = 0;
7223 D(emitcode ("; genDataPointerGet",""));
7225 aopOp (result, ic, TRUE);
7227 /* get the string representation of the name */
7228 l = aopGet (AOP (left), 0, FALSE, TRUE);
7229 size = AOP_SIZE (result);
7233 sprintf (buffer, "(%s + %d)", l + 1, offset);
7235 sprintf (buffer, "%s", l + 1);
7236 aopPut (AOP (result), buffer, offset++);
7239 freeAsmop (left, NULL, ic, TRUE);
7240 freeAsmop (result, NULL, ic, TRUE);
7243 /*-----------------------------------------------------------------*/
7244 /* genNearPointerGet - emitcode for near pointer fetch */
7245 /*-----------------------------------------------------------------*/
7247 genNearPointerGet (operand * left,
7255 sym_link *rtype, *retype;
7256 sym_link *ltype = operandType (left);
7259 D(emitcode ("; genNearPointerGet",""));
7261 rtype = operandType (result);
7262 retype = getSpec (rtype);
7264 aopOp (left, ic, FALSE);
7266 /* if left is rematerialisable and
7267 result is not bit variable type and
7268 the left is pointer to data space i.e
7269 lower 128 bytes of space */
7270 if (AOP_TYPE (left) == AOP_IMMD &&
7271 !IS_BITVAR (retype) &&
7272 DCL_TYPE (ltype) == POINTER)
7274 genDataPointerGet (left, result, ic);
7278 /* if the value is already in a pointer register
7279 then don't need anything more */
7280 if (!AOP_INPREG (AOP (left)))
7282 /* otherwise get a free pointer register */
7284 preg = getFreePtr (ic, &aop, FALSE);
7285 emitcode ("mov", "%s,%s",
7287 aopGet (AOP (left), 0, FALSE, TRUE));
7291 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7293 //aopOp (result, ic, FALSE);
7294 aopOp (result, ic, result?TRUE:FALSE);
7296 /* if bitfield then unpack the bits */
7297 if (IS_BITVAR (retype))
7298 genUnpackBits (result, rname, POINTER);
7301 /* we have can just get the values */
7302 int size = AOP_SIZE (result);
7307 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7310 emitcode ("mov", "a,@%s", rname);
7311 aopPut (AOP (result), "a", offset);
7315 sprintf (buffer, "@%s", rname);
7316 aopPut (AOP (result), buffer, offset);
7320 emitcode ("inc", "%s", rname);
7324 /* now some housekeeping stuff */
7325 if (aop) /* we had to allocate for this iCode */
7327 if (pi) { /* post increment present */
7328 aopPut(AOP ( left ),rname,0);
7330 freeAsmop (NULL, aop, ic, TRUE);
7334 /* we did not allocate which means left
7335 already in a pointer register, then
7336 if size > 0 && this could be used again
7337 we have to point it back to where it
7339 if ((AOP_SIZE (result) > 1 &&
7340 !OP_SYMBOL (left)->remat &&
7341 (OP_SYMBOL (left)->liveTo > ic->seq ||
7345 int size = AOP_SIZE (result) - 1;
7347 emitcode ("dec", "%s", rname);
7352 freeAsmop (left, NULL, ic, TRUE);
7353 freeAsmop (result, NULL, ic, TRUE);
7354 if (pi) pi->generated = 1;
7357 /*-----------------------------------------------------------------*/
7358 /* genPagedPointerGet - emitcode for paged pointer fetch */
7359 /*-----------------------------------------------------------------*/
7361 genPagedPointerGet (operand * left,
7369 sym_link *rtype, *retype;
7371 D(emitcode ("; genPagedPointerGet",""));
7373 rtype = operandType (result);
7374 retype = getSpec (rtype);
7376 aopOp (left, ic, FALSE);
7378 /* if the value is already in a pointer register
7379 then don't need anything more */
7380 if (!AOP_INPREG (AOP (left)))
7382 /* otherwise get a free pointer register */
7384 preg = getFreePtr (ic, &aop, FALSE);
7385 emitcode ("mov", "%s,%s",
7387 aopGet (AOP (left), 0, FALSE, TRUE));
7391 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7393 aopOp (result, ic, FALSE);
7395 /* if bitfield then unpack the bits */
7396 if (IS_BITVAR (retype))
7397 genUnpackBits (result, rname, PPOINTER);
7400 /* we have can just get the values */
7401 int size = AOP_SIZE (result);
7407 emitcode ("movx", "a,@%s", rname);
7408 aopPut (AOP (result), "a", offset);
7413 emitcode ("inc", "%s", rname);
7417 /* now some housekeeping stuff */
7418 if (aop) /* we had to allocate for this iCode */
7420 if (pi) aopPut ( AOP (left), rname, 0);
7421 freeAsmop (NULL, aop, ic, TRUE);
7425 /* we did not allocate which means left
7426 already in a pointer register, then
7427 if size > 0 && this could be used again
7428 we have to point it back to where it
7430 if ((AOP_SIZE (result) > 1 &&
7431 !OP_SYMBOL (left)->remat &&
7432 (OP_SYMBOL (left)->liveTo > ic->seq ||
7436 int size = AOP_SIZE (result) - 1;
7438 emitcode ("dec", "%s", rname);
7443 freeAsmop (left, NULL, ic, TRUE);
7444 freeAsmop (result, NULL, ic, TRUE);
7445 if (pi) pi->generated = 1;
7449 /*-----------------------------------------------------------------*/
7450 /* genFarPointerGet - gget value from far space */
7451 /*-----------------------------------------------------------------*/
7453 genFarPointerGet (operand * left,
7454 operand * result, iCode * ic, iCode * pi)
7457 sym_link *retype = getSpec (operandType (result));
7459 D(emitcode ("; genFarPointerGet",""));
7461 aopOp (left, ic, FALSE);
7463 /* if the operand is already in dptr
7464 then we do nothing else we move the value to dptr */
7465 if (AOP_TYPE (left) != AOP_STR)
7467 /* if this is remateriazable */
7468 if (AOP_TYPE (left) == AOP_IMMD)
7469 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7471 { /* we need to get it byte by byte */
7472 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7473 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7476 /* so dptr know contains the address */
7477 aopOp (result, ic, FALSE);
7479 /* if bit then unpack */
7480 if (IS_BITVAR (retype))
7481 genUnpackBits (result, "dptr", FPOINTER);
7484 size = AOP_SIZE (result);
7489 emitcode ("movx", "a,@dptr");
7490 aopPut (AOP (result), "a", offset++);
7492 emitcode ("inc", "dptr");
7496 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7497 aopPut ( AOP (left), "dpl", 0);
7498 aopPut ( AOP (left), "dph", 1);
7501 freeAsmop (left, NULL, ic, TRUE);
7502 freeAsmop (result, NULL, ic, TRUE);
7505 /*-----------------------------------------------------------------*/
7506 /* genCodePointerGet - gget value from code space */
7507 /*-----------------------------------------------------------------*/
7509 genCodePointerGet (operand * left,
7510 operand * result, iCode * ic, iCode *pi)
7513 sym_link *retype = getSpec (operandType (result));
7515 D(emitcode ("; genCodePointerGet",""));
7517 aopOp (left, ic, FALSE);
7519 /* if the operand is already in dptr
7520 then we do nothing else we move the value to dptr */
7521 if (AOP_TYPE (left) != AOP_STR)
7523 /* if this is remateriazable */
7524 if (AOP_TYPE (left) == AOP_IMMD)
7525 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7527 { /* we need to get it byte by byte */
7528 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7529 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7532 /* so dptr know contains the address */
7533 aopOp (result, ic, FALSE);
7535 /* if bit then unpack */
7536 if (IS_BITVAR (retype))
7537 genUnpackBits (result, "dptr", CPOINTER);
7540 size = AOP_SIZE (result);
7545 emitcode ("clr", "a");
7546 emitcode ("movc", "a,@a+dptr");
7547 aopPut (AOP (result), "a", offset++);
7549 emitcode ("inc", "dptr");
7553 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7554 aopPut ( AOP (left), "dpl", 0);
7555 aopPut ( AOP (left), "dph", 1);
7558 freeAsmop (left, NULL, ic, TRUE);
7559 freeAsmop (result, NULL, ic, TRUE);
7562 /*-----------------------------------------------------------------*/
7563 /* genGenPointerGet - gget value from generic pointer space */
7564 /*-----------------------------------------------------------------*/
7566 genGenPointerGet (operand * left,
7567 operand * result, iCode * ic, iCode *pi)
7570 sym_link *retype = getSpec (operandType (result));
7572 D(emitcode ("; genGenPointerGet",""));
7574 aopOp (left, ic, FALSE);
7576 /* if the operand is already in dptr
7577 then we do nothing else we move the value to dptr */
7578 if (AOP_TYPE (left) != AOP_STR)
7580 /* if this is remateriazable */
7581 if (AOP_TYPE (left) == AOP_IMMD)
7583 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7584 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7585 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7587 emitcode ("mov", "b,#%d", pointerCode (retype));
7590 { /* we need to get it byte by byte */
7591 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7592 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7593 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7596 /* so dptr know contains the address */
7597 aopOp (result, ic, FALSE);
7599 /* if bit then unpack */
7600 if (IS_BITVAR (retype))
7601 genUnpackBits (result, "dptr", GPOINTER);
7604 size = AOP_SIZE (result);
7609 emitcode ("lcall", "__gptrget");
7610 aopPut (AOP (result), "a", offset++);
7612 emitcode ("inc", "dptr");
7616 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7617 aopPut ( AOP (left), "dpl", 0);
7618 aopPut ( AOP (left), "dph", 1);
7619 aopPut ( AOP (left), "b", 2);
7622 freeAsmop (left, NULL, ic, TRUE);
7623 freeAsmop (result, NULL, ic, TRUE);
7626 /*-----------------------------------------------------------------*/
7627 /* genPointerGet - generate code for pointer get */
7628 /*-----------------------------------------------------------------*/
7630 genPointerGet (iCode * ic, iCode *pi)
7632 operand *left, *result;
7633 sym_link *type, *etype;
7636 D(emitcode ("; genPointerGet",""));
7638 left = IC_LEFT (ic);
7639 result = IC_RESULT (ic);
7641 /* depending on the type of pointer we need to
7642 move it to the correct pointer register */
7643 type = operandType (left);
7644 etype = getSpec (type);
7645 /* if left is of type of pointer then it is simple */
7646 if (IS_PTR (type) && !IS_FUNC (type->next))
7647 p_type = DCL_TYPE (type);
7650 /* we have to go by the storage class */
7651 p_type = PTR_TYPE (SPEC_OCLS (etype));
7654 /* special case when cast remat */
7655 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7656 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7657 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7658 type = operandType (left);
7659 p_type = DCL_TYPE (type);
7661 /* now that we have the pointer type we assign
7662 the pointer values */
7668 genNearPointerGet (left, result, ic, pi);
7672 genPagedPointerGet (left, result, ic, pi);
7676 genFarPointerGet (left, result, ic, pi);
7680 genCodePointerGet (left, result, ic, pi);
7684 genGenPointerGet (left, result, ic, pi);
7690 /*-----------------------------------------------------------------*/
7691 /* genPackBits - generates code for packed bit storage */
7692 /*-----------------------------------------------------------------*/
7694 genPackBits (sym_link * etype,
7696 char *rname, int p_type)
7704 D(emitcode ("; genPackBits",""));
7706 blen = SPEC_BLEN (etype);
7707 bstr = SPEC_BSTR (etype);
7709 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7712 /* if the bit lenth is less than or */
7713 /* it exactly fits a byte then */
7714 if (SPEC_BLEN (etype) <= 8)
7716 shCount = SPEC_BSTR (etype);
7718 /* shift left acc */
7721 if (SPEC_BLEN (etype) < 8)
7722 { /* if smaller than a byte */
7728 emitcode ("mov", "b,a");
7729 emitcode ("mov", "a,@%s", rname);
7733 emitcode ("mov", "b,a");
7734 emitcode ("movx", "a,@dptr");
7738 emitcode ("push", "b");
7739 emitcode ("push", "acc");
7740 emitcode ("lcall", "__gptrget");
7741 emitcode ("pop", "b");
7745 emitcode ("anl", "a,#0x%02x", (unsigned char)
7746 ((unsigned char) (0xFF << (blen + bstr)) |
7747 (unsigned char) (0xFF >> (8 - bstr))));
7748 emitcode ("orl", "a,b");
7749 if (p_type == GPOINTER)
7750 emitcode ("pop", "b");
7757 emitcode ("mov", "@%s,a", rname);
7761 emitcode ("movx", "@dptr,a");
7765 emitcode ("lcall", "__gptrput");
7770 if (SPEC_BLEN (etype) <= 8)
7773 emitcode ("inc", "%s", rname);
7774 rLen = SPEC_BLEN (etype);
7776 /* now generate for lengths greater than one byte */
7780 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7792 emitcode ("mov", "@%s,a", rname);
7795 emitcode ("mov", "@%s,%s", rname, l);
7800 emitcode ("movx", "@dptr,a");
7805 emitcode ("lcall", "__gptrput");
7808 emitcode ("inc", "%s", rname);
7813 /* last last was not complete */
7816 /* save the byte & read byte */
7820 emitcode ("mov", "b,a");
7821 emitcode ("mov", "a,@%s", rname);
7825 emitcode ("mov", "b,a");
7826 emitcode ("movx", "a,@dptr");
7830 emitcode ("push", "b");
7831 emitcode ("push", "acc");
7832 emitcode ("lcall", "__gptrget");
7833 emitcode ("pop", "b");
7837 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7838 emitcode ("orl", "a,b");
7841 if (p_type == GPOINTER)
7842 emitcode ("pop", "b");
7848 emitcode ("mov", "@%s,a", rname);
7852 emitcode ("movx", "@dptr,a");
7856 emitcode ("lcall", "__gptrput");
7860 /*-----------------------------------------------------------------*/
7861 /* genDataPointerSet - remat pointer to data space */
7862 /*-----------------------------------------------------------------*/
7864 genDataPointerSet (operand * right,
7868 int size, offset = 0;
7869 char *l, buffer[256];
7871 D(emitcode ("; genDataPointerSet",""));
7873 aopOp (right, ic, FALSE);
7875 l = aopGet (AOP (result), 0, FALSE, TRUE);
7876 size = AOP_SIZE (right);
7880 sprintf (buffer, "(%s + %d)", l + 1, offset);
7882 sprintf (buffer, "%s", l + 1);
7883 emitcode ("mov", "%s,%s", buffer,
7884 aopGet (AOP (right), offset++, FALSE, FALSE));
7887 freeAsmop (right, NULL, ic, TRUE);
7888 freeAsmop (result, NULL, ic, TRUE);
7891 /*-----------------------------------------------------------------*/
7892 /* genNearPointerSet - emitcode for near pointer put */
7893 /*-----------------------------------------------------------------*/
7895 genNearPointerSet (operand * right,
7903 sym_link *retype, *letype;
7904 sym_link *ptype = operandType (result);
7906 D(emitcode ("; genNearPointerSet",""));
7908 retype = getSpec (operandType (right));
7909 letype = getSpec (ptype);
7910 aopOp (result, ic, FALSE);
7912 /* if the result is rematerializable &
7913 in data space & not a bit variable */
7914 if (AOP_TYPE (result) == AOP_IMMD &&
7915 DCL_TYPE (ptype) == POINTER &&
7916 !IS_BITVAR (retype) &&
7917 !IS_BITVAR (letype))
7919 genDataPointerSet (right, result, ic);
7923 /* if the value is already in a pointer register
7924 then don't need anything more */
7925 if (!AOP_INPREG (AOP (result)))
7928 //AOP_TYPE (result) == AOP_STK
7932 // Aha, it is a pointer, just in disguise.
7933 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7936 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7937 __FILE__, __LINE__);
7942 rname++; // skip the '@'.
7947 /* otherwise get a free pointer register */
7949 preg = getFreePtr (ic, &aop, FALSE);
7950 emitcode ("mov", "%s,%s",
7952 aopGet (AOP (result), 0, FALSE, TRUE));
7958 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7961 aopOp (right, ic, FALSE);
7963 /* if bitfield then unpack the bits */
7964 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7965 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7968 /* we have can just get the values */
7969 int size = AOP_SIZE (right);
7974 l = aopGet (AOP (right), offset, FALSE, TRUE);
7978 emitcode ("mov", "@%s,a", rname);
7981 emitcode ("mov", "@%s,%s", rname, l);
7983 emitcode ("inc", "%s", rname);
7988 /* now some housekeeping stuff */
7989 if (aop) /* we had to allocate for this iCode */
7991 if (pi) aopPut (AOP (result),rname,0);
7992 freeAsmop (NULL, aop, ic, TRUE);
7996 /* we did not allocate which means left
7997 already in a pointer register, then
7998 if size > 0 && this could be used again
7999 we have to point it back to where it
8001 if ((AOP_SIZE (right) > 1 &&
8002 !OP_SYMBOL (result)->remat &&
8003 (OP_SYMBOL (result)->liveTo > ic->seq ||
8007 int size = AOP_SIZE (right) - 1;
8009 emitcode ("dec", "%s", rname);
8014 if (pi) pi->generated = 1;
8015 freeAsmop (result, NULL, ic, TRUE);
8016 freeAsmop (right, NULL, ic, TRUE);
8019 /*-----------------------------------------------------------------*/
8020 /* genPagedPointerSet - emitcode for Paged pointer put */
8021 /*-----------------------------------------------------------------*/
8023 genPagedPointerSet (operand * right,
8031 sym_link *retype, *letype;
8033 D(emitcode ("; genPagedPointerSet",""));
8035 retype = getSpec (operandType (right));
8036 letype = getSpec (operandType (result));
8038 aopOp (result, ic, FALSE);
8040 /* if the value is already in a pointer register
8041 then don't need anything more */
8042 if (!AOP_INPREG (AOP (result)))
8044 /* otherwise get a free pointer register */
8046 preg = getFreePtr (ic, &aop, FALSE);
8047 emitcode ("mov", "%s,%s",
8049 aopGet (AOP (result), 0, FALSE, TRUE));
8053 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8055 aopOp (right, ic, FALSE);
8057 /* if bitfield then unpack the bits */
8058 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8059 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8062 /* we have can just get the values */
8063 int size = AOP_SIZE (right);
8068 l = aopGet (AOP (right), offset, FALSE, TRUE);
8071 emitcode ("movx", "@%s,a", rname);
8074 emitcode ("inc", "%s", rname);
8080 /* now some housekeeping stuff */
8081 if (aop) /* we had to allocate for this iCode */
8083 if (pi) aopPut (AOP (result),rname,0);
8084 freeAsmop (NULL, aop, ic, TRUE);
8088 /* we did not allocate which means left
8089 already in a pointer register, then
8090 if size > 0 && this could be used again
8091 we have to point it back to where it
8093 if (AOP_SIZE (right) > 1 &&
8094 !OP_SYMBOL (result)->remat &&
8095 (OP_SYMBOL (result)->liveTo > ic->seq ||
8098 int size = AOP_SIZE (right) - 1;
8100 emitcode ("dec", "%s", rname);
8105 if (pi) pi->generated = 1;
8106 freeAsmop (result, NULL, ic, TRUE);
8107 freeAsmop (right, NULL, ic, TRUE);
8112 /*-----------------------------------------------------------------*/
8113 /* genFarPointerSet - set value from far space */
8114 /*-----------------------------------------------------------------*/
8116 genFarPointerSet (operand * right,
8117 operand * result, iCode * ic, iCode * pi)
8120 sym_link *retype = getSpec (operandType (right));
8121 sym_link *letype = getSpec (operandType (result));
8123 D(emitcode ("; genFarPointerSet",""));
8125 aopOp (result, ic, FALSE);
8127 /* if the operand is already in dptr
8128 then we do nothing else we move the value to dptr */
8129 if (AOP_TYPE (result) != AOP_STR)
8131 /* if this is remateriazable */
8132 if (AOP_TYPE (result) == AOP_IMMD)
8133 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8135 { /* we need to get it byte by byte */
8136 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8137 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8140 /* so dptr know contains the address */
8141 aopOp (right, ic, FALSE);
8143 /* if bit then unpack */
8144 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8145 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8148 size = AOP_SIZE (right);
8153 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8155 emitcode ("movx", "@dptr,a");
8157 emitcode ("inc", "dptr");
8160 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8161 aopPut (AOP(result),"dpl",0);
8162 aopPut (AOP(result),"dph",1);
8165 freeAsmop (result, NULL, ic, TRUE);
8166 freeAsmop (right, NULL, ic, TRUE);
8169 /*-----------------------------------------------------------------*/
8170 /* genGenPointerSet - set value from generic pointer space */
8171 /*-----------------------------------------------------------------*/
8173 genGenPointerSet (operand * right,
8174 operand * result, iCode * ic, iCode * pi)
8177 sym_link *retype = getSpec (operandType (right));
8178 sym_link *letype = getSpec (operandType (result));
8180 D(emitcode ("; genGenPointerSet",""));
8182 aopOp (result, ic, FALSE);
8184 /* if the operand is already in dptr
8185 then we do nothing else we move the value to dptr */
8186 if (AOP_TYPE (result) != AOP_STR)
8188 /* if this is remateriazable */
8189 if (AOP_TYPE (result) == AOP_IMMD)
8191 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8192 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8193 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8195 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8198 { /* we need to get it byte by byte */
8199 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8200 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8201 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8204 /* so dptr know contains the address */
8205 aopOp (right, ic, FALSE);
8207 /* if bit then unpack */
8208 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8209 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8212 size = AOP_SIZE (right);
8217 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8219 emitcode ("lcall", "__gptrput");
8221 emitcode ("inc", "dptr");
8225 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8226 aopPut (AOP(result),"dpl",0);
8227 aopPut (AOP(result),"dph",1);
8228 aopPut (AOP(result),"b",2);
8231 freeAsmop (result, NULL, ic, TRUE);
8232 freeAsmop (right, NULL, ic, TRUE);
8235 /*-----------------------------------------------------------------*/
8236 /* genPointerSet - stores the value into a pointer location */
8237 /*-----------------------------------------------------------------*/
8239 genPointerSet (iCode * ic, iCode *pi)
8241 operand *right, *result;
8242 sym_link *type, *etype;
8245 D(emitcode ("; genPointerSet",""));
8247 right = IC_RIGHT (ic);
8248 result = IC_RESULT (ic);
8250 /* depending on the type of pointer we need to
8251 move it to the correct pointer register */
8252 type = operandType (result);
8253 etype = getSpec (type);
8254 /* if left is of type of pointer then it is simple */
8255 if (IS_PTR (type) && !IS_FUNC (type->next))
8257 p_type = DCL_TYPE (type);
8261 /* we have to go by the storage class */
8262 p_type = PTR_TYPE (SPEC_OCLS (etype));
8265 /* special case when cast remat */
8266 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8267 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8268 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8269 type = operandType (result);
8270 p_type = DCL_TYPE (type);
8272 /* now that we have the pointer type we assign
8273 the pointer values */
8279 genNearPointerSet (right, result, ic, pi);
8283 genPagedPointerSet (right, result, ic, pi);
8287 genFarPointerSet (right, result, ic, pi);
8291 genGenPointerSet (right, result, ic, pi);
8295 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8296 "genPointerSet: illegal pointer type");
8301 /*-----------------------------------------------------------------*/
8302 /* genIfx - generate code for Ifx statement */
8303 /*-----------------------------------------------------------------*/
8305 genIfx (iCode * ic, iCode * popIc)
8307 operand *cond = IC_COND (ic);
8310 D(emitcode ("; genIfx",""));
8312 aopOp (cond, ic, FALSE);
8314 /* get the value into acc */
8315 if (AOP_TYPE (cond) != AOP_CRY)
8319 /* the result is now in the accumulator */
8320 freeAsmop (cond, NULL, ic, TRUE);
8322 /* if there was something to be popped then do it */
8326 /* if the condition is a bit variable */
8327 if (isbit && IS_ITEMP (cond) &&
8329 genIfxJump (ic, SPIL_LOC (cond)->rname);
8330 else if (isbit && !IS_ITEMP (cond))
8331 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8333 genIfxJump (ic, "a");
8338 /*-----------------------------------------------------------------*/
8339 /* genAddrOf - generates code for address of */
8340 /*-----------------------------------------------------------------*/
8342 genAddrOf (iCode * ic)
8344 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8347 D(emitcode ("; genAddrOf",""));
8349 aopOp (IC_RESULT (ic), ic, FALSE);
8351 /* if the operand is on the stack then we
8352 need to get the stack offset of this
8356 /* if it has an offset then we need to compute
8360 emitcode ("mov", "a,_bp");
8361 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8362 ((char) (sym->stack - _G.nRegsSaved)) :
8363 ((char) sym->stack)) & 0xff);
8364 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8368 /* we can just move _bp */
8369 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8371 /* fill the result with zero */
8372 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8377 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8383 /* object not on stack then we need the name */
8384 size = AOP_SIZE (IC_RESULT (ic));
8389 char s[SDCC_NAME_MAX];
8391 sprintf (s, "#(%s >> %d)",
8395 sprintf (s, "#%s", sym->rname);
8396 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8400 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8404 /*-----------------------------------------------------------------*/
8405 /* genFarFarAssign - assignment when both are in far space */
8406 /*-----------------------------------------------------------------*/
8408 genFarFarAssign (operand * result, operand * right, iCode * ic)
8410 int size = AOP_SIZE (right);
8414 D(emitcode ("; genFarFarAssign",""));
8416 /* first push the right side on to the stack */
8419 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8421 emitcode ("push", "acc");
8424 freeAsmop (right, NULL, ic, FALSE);
8425 /* now assign DPTR to result */
8426 aopOp (result, ic, FALSE);
8427 size = AOP_SIZE (result);
8430 emitcode ("pop", "acc");
8431 aopPut (AOP (result), "a", --offset);
8433 freeAsmop (result, NULL, ic, FALSE);
8437 /*-----------------------------------------------------------------*/
8438 /* genAssign - generate code for assignment */
8439 /*-----------------------------------------------------------------*/
8441 genAssign (iCode * ic)
8443 operand *result, *right;
8445 unsigned long lit = 0L;
8447 D(emitcode("; genAssign",""));
8449 result = IC_RESULT (ic);
8450 right = IC_RIGHT (ic);
8452 /* if they are the same */
8453 if (operandsEqu (result, right)) {
8457 aopOp (right, ic, FALSE);
8459 /* special case both in far space */
8460 if (AOP_TYPE (right) == AOP_DPTR &&
8461 IS_TRUE_SYMOP (result) &&
8462 isOperandInFarSpace (result))
8465 genFarFarAssign (result, right, ic);
8469 aopOp (result, ic, TRUE);
8471 /* if they are the same registers */
8472 if (sameRegs (AOP (right), AOP (result)))
8475 /* if the result is a bit */
8476 if (AOP_TYPE (result) == AOP_CRY)
8479 /* if the right size is a literal then
8480 we know what the value is */
8481 if (AOP_TYPE (right) == AOP_LIT)
8483 if (((int) operandLitValue (right)))
8484 aopPut (AOP (result), one, 0);
8486 aopPut (AOP (result), zero, 0);
8490 /* the right is also a bit variable */
8491 if (AOP_TYPE (right) == AOP_CRY)
8493 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8494 aopPut (AOP (result), "c", 0);
8500 aopPut (AOP (result), "a", 0);
8504 /* bit variables done */
8506 size = AOP_SIZE (result);
8508 if (AOP_TYPE (right) == AOP_LIT)
8509 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8511 (AOP_TYPE (result) != AOP_REG) &&
8512 (AOP_TYPE (right) == AOP_LIT) &&
8513 !IS_FLOAT (operandType (right)) &&
8516 emitcode ("clr", "a");
8519 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8520 aopPut (AOP (result), "a", size);
8522 aopPut (AOP (result),
8523 aopGet (AOP (right), size, FALSE, FALSE),
8531 aopPut (AOP (result),
8532 aopGet (AOP (right), offset, FALSE, FALSE),
8539 freeAsmop (right, NULL, ic, TRUE);
8540 freeAsmop (result, NULL, ic, TRUE);
8543 /*-----------------------------------------------------------------*/
8544 /* genJumpTab - genrates code for jump table */
8545 /*-----------------------------------------------------------------*/
8547 genJumpTab (iCode * ic)
8552 D(emitcode ("; genJumpTab",""));
8554 aopOp (IC_JTCOND (ic), ic, FALSE);
8555 /* get the condition into accumulator */
8556 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8558 /* multiply by three */
8559 emitcode ("add", "a,acc");
8560 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8561 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8563 jtab = newiTempLabel (NULL);
8564 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8565 emitcode ("jmp", "@a+dptr");
8566 emitcode ("", "%05d$:", jtab->key + 100);
8567 /* now generate the jump labels */
8568 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8569 jtab = setNextItem (IC_JTLABELS (ic)))
8570 emitcode ("ljmp", "%05d$", jtab->key + 100);
8574 /*-----------------------------------------------------------------*/
8575 /* genCast - gen code for casting */
8576 /*-----------------------------------------------------------------*/
8578 genCast (iCode * ic)
8580 operand *result = IC_RESULT (ic);
8581 sym_link *ctype = operandType (IC_LEFT (ic));
8582 sym_link *rtype = operandType (IC_RIGHT (ic));
8583 operand *right = IC_RIGHT (ic);
8586 D(emitcode("; genCast",""));
8588 /* if they are equivalent then do nothing */
8589 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8592 aopOp (right, ic, FALSE);
8593 aopOp (result, ic, FALSE);
8595 /* if the result is a bit */
8596 if (IS_BITVAR(OP_SYMBOL(result)->type))
8598 /* if the right size is a literal then
8599 we know what the value is */
8600 if (AOP_TYPE (right) == AOP_LIT)
8602 if (((int) operandLitValue (right)))
8603 aopPut (AOP (result), one, 0);
8605 aopPut (AOP (result), zero, 0);
8610 /* the right is also a bit variable */
8611 if (AOP_TYPE (right) == AOP_CRY)
8613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8614 aopPut (AOP (result), "c", 0);
8620 aopPut (AOP (result), "a", 0);
8624 /* if they are the same size : or less */
8625 if (AOP_SIZE (result) <= AOP_SIZE (right))
8628 /* if they are in the same place */
8629 if (sameRegs (AOP (right), AOP (result)))
8632 /* if they in different places then copy */
8633 size = AOP_SIZE (result);
8637 aopPut (AOP (result),
8638 aopGet (AOP (right), offset, FALSE, FALSE),
8646 /* if the result is of type pointer */
8651 sym_link *type = operandType (right);
8652 sym_link *etype = getSpec (type);
8654 /* pointer to generic pointer */
8655 if (IS_GENPTR (ctype))
8658 p_type = DCL_TYPE (type);
8661 if (SPEC_SCLS(etype)==S_REGISTER) {
8662 // let's assume it is a generic pointer
8665 /* we have to go by the storage class */
8666 p_type = PTR_TYPE (SPEC_OCLS (etype));
8670 /* the first two bytes are known */
8671 size = GPTRSIZE - 1;
8675 aopPut (AOP (result),
8676 aopGet (AOP (right), offset, FALSE, FALSE),
8680 /* the last byte depending on type */
8682 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8687 // pointerTypeToGPByte will have bitched.
8691 sprintf(gpValStr, "#0x%d", gpVal);
8692 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8697 /* just copy the pointers */
8698 size = AOP_SIZE (result);
8702 aopPut (AOP (result),
8703 aopGet (AOP (right), offset, FALSE, FALSE),
8710 /* so we now know that the size of destination is greater
8711 than the size of the source */
8712 /* we move to result for the size of source */
8713 size = AOP_SIZE (right);
8717 aopPut (AOP (result),
8718 aopGet (AOP (right), offset, FALSE, FALSE),
8723 /* now depending on the sign of the source && destination */
8724 size = AOP_SIZE (result) - AOP_SIZE (right);
8725 /* if unsigned or not an integral type */
8726 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8729 aopPut (AOP (result), zero, offset++);
8733 /* we need to extend the sign :{ */
8734 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8737 emitcode ("rlc", "a");
8738 emitcode ("subb", "a,acc");
8740 aopPut (AOP (result), "a", offset++);
8743 /* we are done hurray !!!! */
8746 freeAsmop (right, NULL, ic, TRUE);
8747 freeAsmop (result, NULL, ic, TRUE);
8751 /*-----------------------------------------------------------------*/
8752 /* genDjnz - generate decrement & jump if not zero instrucion */
8753 /*-----------------------------------------------------------------*/
8755 genDjnz (iCode * ic, iCode * ifx)
8761 D(emitcode ("; genDjnz",""));
8763 /* if the if condition has a false label
8764 then we cannot save */
8768 /* if the minus is not of the form
8770 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8771 !IS_OP_LITERAL (IC_RIGHT (ic)))
8774 if (operandLitValue (IC_RIGHT (ic)) != 1)
8777 /* if the size of this greater than one then no
8779 if (getSize (operandType (IC_RESULT (ic))) > 1)
8782 /* otherwise we can save BIG */
8783 lbl = newiTempLabel (NULL);
8784 lbl1 = newiTempLabel (NULL);
8786 aopOp (IC_RESULT (ic), ic, FALSE);
8788 if (AOP_NEEDSACC(IC_RESULT(ic)))
8790 /* If the result is accessed indirectly via
8791 * the accumulator, we must explicitly write
8792 * it back after the decrement.
8794 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8796 if (strcmp(rByte, "a"))
8798 /* Something is hopelessly wrong */
8799 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8800 __FILE__, __LINE__);
8801 /* We can just give up; the generated code will be inefficient,
8804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8807 emitcode ("dec", "%s", rByte);
8808 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8809 emitcode ("jnz", "%05d$", lbl->key + 100);
8811 else if (IS_AOP_PREG (IC_RESULT (ic)))
8813 emitcode ("dec", "%s",
8814 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8815 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8816 emitcode ("jnz", "%05d$", lbl->key + 100);
8820 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8823 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8824 emitcode ("", "%05d$:", lbl->key + 100);
8825 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8826 emitcode ("", "%05d$:", lbl1->key + 100);
8828 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8833 /*-----------------------------------------------------------------*/
8834 /* genReceive - generate code for a receive iCode */
8835 /*-----------------------------------------------------------------*/
8837 genReceive (iCode * ic)
8839 int size = getSize (operandType (IC_RESULT (ic)));
8841 D(emitcode ("; genReceive",""));
8843 if (ic->argreg == 1) { /* first parameter */
8844 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8845 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8846 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8848 offset = fReturnSizeMCS51 - size;
8850 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8851 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8854 aopOp (IC_RESULT (ic), ic, FALSE);
8855 size = AOP_SIZE (IC_RESULT (ic));
8858 emitcode ("pop", "acc");
8859 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8864 aopOp (IC_RESULT (ic), ic, FALSE);
8866 assignResultValue (IC_RESULT (ic));
8868 } else { /* second receive onwards */
8870 aopOp (IC_RESULT (ic), ic, FALSE);
8871 rb1off = ic->argreg;
8873 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8876 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8879 /*-----------------------------------------------------------------*/
8880 /* gen51Code - generate code for 8051 based controllers */
8881 /*-----------------------------------------------------------------*/
8883 gen51Code (iCode * lic)
8888 lineHead = lineCurr = NULL;
8890 /* print the allocation information */
8892 printAllocInfo (currFunc, codeOutFile);
8893 /* if debug information required */
8894 if (options.debug && currFunc)
8896 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8898 if (IS_STATIC (currFunc->etype))
8899 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8901 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8904 /* stack pointer name */
8905 if (options.useXstack)
8911 for (ic = lic; ic; ic = ic->next)
8914 if (ic->lineno && cln != ic->lineno)
8919 emitcode ("", "C$%s$%d$%d$%d ==.",
8920 FileBaseName (ic->filename), ic->lineno,
8921 ic->level, ic->block);
8924 if (!options.noCcodeInAsm) {
8925 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8926 printCLine(ic->filename, ic->lineno));
8930 if (options.iCodeInAsm) {
8931 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8933 /* if the result is marked as
8934 spilt and rematerializable or code for
8935 this has already been generated then
8937 if (resultRemat (ic) || ic->generated)
8940 /* depending on the operation */
8960 /* IPOP happens only when trying to restore a
8961 spilt live range, if there is an ifx statement
8962 following this pop then the if statement might
8963 be using some of the registers being popped which
8964 would destory the contents of the register so
8965 we need to check for this condition and handle it */
8967 ic->next->op == IFX &&
8968 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8969 genIfx (ic->next, ic);
8987 genEndFunction (ic);
9007 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9024 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9028 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9035 /* note these two are xlated by algebraic equivalence
9036 during parsing SDCC.y */
9037 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9038 "got '>=' or '<=' shouldn't have come here");
9042 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9054 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9058 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9062 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9089 case GET_VALUE_AT_ADDRESS:
9090 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9094 if (POINTER_SET (ic))
9095 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9121 addSet (&_G.sendSet, ic);
9130 /* now we are ready to call the
9131 peep hole optimizer */
9132 if (!options.nopeep)
9133 peepHole (&lineHead);
9135 /* now do the actual printing */
9136 printLine (lineHead, codeOutFile);