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 need to flip the
1448 first it then copy the rest in place */
1449 size = AOP_SIZE (op) - 1;
1450 l = aopGet (AOP (op), 3, FALSE, FALSE);
1454 emitcode ("cpl", "acc.7");
1455 aopPut (AOP (result), "a", 3);
1459 aopPut (AOP (result),
1460 aopGet (AOP (op), offset, FALSE, FALSE),
1466 /*-----------------------------------------------------------------*/
1467 /* genUminus - unary minus code generation */
1468 /*-----------------------------------------------------------------*/
1470 genUminus (iCode * ic)
1473 sym_link *optype, *rtype;
1476 D(emitcode ("; genUminus",""));
1479 aopOp (IC_LEFT (ic), ic, FALSE);
1480 aopOp (IC_RESULT (ic), ic, TRUE);
1482 /* if both in bit space then special
1484 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1485 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1488 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1489 emitcode ("cpl", "c");
1490 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1494 optype = operandType (IC_LEFT (ic));
1495 rtype = operandType (IC_RESULT (ic));
1497 /* if float then do float stuff */
1498 if (IS_FLOAT (optype))
1500 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1504 /* otherwise subtract from zero */
1505 size = AOP_SIZE (IC_LEFT (ic));
1510 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1511 if (!strcmp (l, "a"))
1515 emitcode ("cpl", "a");
1516 emitcode ("addc", "a,#0");
1522 emitcode ("clr", "a");
1523 emitcode ("subb", "a,%s", l);
1525 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1528 /* if any remaining bytes in the result */
1529 /* we just need to propagate the sign */
1530 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1532 emitcode ("rlc", "a");
1533 emitcode ("subb", "a,acc");
1535 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1539 /* release the aops */
1540 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1541 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1544 /*-----------------------------------------------------------------*/
1545 /* saveRegisters - will look for a call and save the registers */
1546 /*-----------------------------------------------------------------*/
1548 saveRegisters (iCode * lic)
1555 for (ic = lic; ic; ic = ic->next)
1556 if (ic->op == CALL || ic->op == PCALL)
1561 fprintf (stderr, "found parameter push with no function call\n");
1565 /* if the registers have been saved already or don't need to be then
1567 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1568 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1571 /* safe the registers in use at this time but skip the
1572 ones for the result */
1573 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1574 mcs51_rUmaskForOp (IC_RESULT(ic)));
1577 if (options.useXstack)
1579 if (bitVectBitValue (rsave, R0_IDX))
1580 emitcode ("mov", "b,r0");
1581 emitcode ("mov", "r0,%s", spname);
1582 for (i = 0; i < mcs51_nRegs; i++)
1584 if (bitVectBitValue (rsave, i))
1587 emitcode ("mov", "a,b");
1589 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1590 emitcode ("movx", "@r0,a");
1591 emitcode ("inc", "r0");
1594 emitcode ("mov", "%s,r0", spname);
1595 if (bitVectBitValue (rsave, R0_IDX))
1596 emitcode ("mov", "r0,b");
1599 for (i = 0; i < mcs51_nRegs; i++)
1601 if (bitVectBitValue (rsave, i))
1602 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1606 /*-----------------------------------------------------------------*/
1607 /* unsaveRegisters - pop the pushed registers */
1608 /*-----------------------------------------------------------------*/
1610 unsaveRegisters (iCode * ic)
1615 /* restore the registers in use at this time but skip the
1616 ones for the result */
1617 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1618 mcs51_rUmaskForOp (IC_RESULT(ic)));
1620 if (options.useXstack)
1622 emitcode ("mov", "r0,%s", spname);
1623 for (i = mcs51_nRegs; i >= 0; i--)
1625 if (bitVectBitValue (rsave, i))
1627 emitcode ("dec", "r0");
1628 emitcode ("movx", "a,@r0");
1630 emitcode ("mov", "b,a");
1632 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1636 emitcode ("mov", "%s,r0", spname);
1637 if (bitVectBitValue (rsave, R0_IDX))
1638 emitcode ("mov", "r0,b");
1641 for (i = mcs51_nRegs; i >= 0; i--)
1643 if (bitVectBitValue (rsave, i))
1644 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1650 /*-----------------------------------------------------------------*/
1652 /*-----------------------------------------------------------------*/
1654 pushSide (operand * oper, int size)
1659 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1660 if (AOP_TYPE (oper) != AOP_REG &&
1661 AOP_TYPE (oper) != AOP_DIR &&
1664 emitcode ("mov", "a,%s", l);
1665 emitcode ("push", "acc");
1668 emitcode ("push", "%s", l);
1672 /*-----------------------------------------------------------------*/
1673 /* assignResultValue - */
1674 /*-----------------------------------------------------------------*/
1676 assignResultValue (operand * oper)
1679 int size = AOP_SIZE (oper);
1682 aopPut (AOP (oper), fReturn[offset], offset);
1688 /*-----------------------------------------------------------------*/
1689 /* genXpush - pushes onto the external stack */
1690 /*-----------------------------------------------------------------*/
1692 genXpush (iCode * ic)
1694 asmop *aop = newAsmop (0);
1696 int size, offset = 0;
1698 D(emitcode ("; genXpush",""));
1700 aopOp (IC_LEFT (ic), ic, FALSE);
1701 r = getFreePtr (ic, &aop, FALSE);
1704 emitcode ("mov", "%s,_spx", r->name);
1706 size = AOP_SIZE (IC_LEFT (ic));
1710 char *l = aopGet (AOP (IC_LEFT (ic)),
1711 offset++, FALSE, FALSE);
1713 emitcode ("movx", "@%s,a", r->name);
1714 emitcode ("inc", "%s", r->name);
1719 emitcode ("mov", "_spx,%s", r->name);
1721 freeAsmop (NULL, aop, ic, TRUE);
1722 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1725 /*-----------------------------------------------------------------*/
1726 /* genIpush - genrate code for pushing this gets a little complex */
1727 /*-----------------------------------------------------------------*/
1729 genIpush (iCode * ic)
1731 int size, offset = 0;
1734 D(emitcode ("; genIpush",""));
1736 /* if this is not a parm push : ie. it is spill push
1737 and spill push is always done on the local stack */
1741 /* and the item is spilt then do nothing */
1742 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1745 aopOp (IC_LEFT (ic), ic, FALSE);
1746 size = AOP_SIZE (IC_LEFT (ic));
1747 /* push it on the stack */
1750 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1756 emitcode ("push", "%s", l);
1761 /* this is a paramter push: in this case we call
1762 the routine to find the call and save those
1763 registers that need to be saved */
1766 /* if use external stack then call the external
1767 stack pushing routine */
1768 if (options.useXstack)
1774 /* then do the push */
1775 aopOp (IC_LEFT (ic), ic, FALSE);
1778 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1779 size = AOP_SIZE (IC_LEFT (ic));
1783 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1784 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1785 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1788 emitcode ("mov", "a,%s", l);
1789 emitcode ("push", "acc");
1792 emitcode ("push", "%s", l);
1795 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1798 /*-----------------------------------------------------------------*/
1799 /* genIpop - recover the registers: can happen only for spilling */
1800 /*-----------------------------------------------------------------*/
1802 genIpop (iCode * ic)
1806 D(emitcode ("; genIpop",""));
1808 /* if the temp was not pushed then */
1809 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1812 aopOp (IC_LEFT (ic), ic, FALSE);
1813 size = AOP_SIZE (IC_LEFT (ic));
1814 offset = (size - 1);
1816 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1819 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1822 /*-----------------------------------------------------------------*/
1823 /* unsaveRBank - restores the resgister bank from stack */
1824 /*-----------------------------------------------------------------*/
1826 unsaveRBank (int bank, iCode * ic, bool popPsw)
1832 if (options.useXstack)
1836 /* Assume r0 is available for use. */
1837 r = mcs51_regWithIdx (R0_IDX);;
1842 r = getFreePtr (ic, &aop, FALSE);
1844 emitcode ("mov", "%s,_spx", r->name);
1849 if (options.useXstack)
1851 emitcode ("movx", "a,@%s", r->name);
1852 emitcode ("mov", "psw,a");
1853 emitcode ("dec", "%s", r->name);
1857 emitcode ("pop", "psw");
1861 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1863 if (options.useXstack)
1865 emitcode ("movx", "a,@%s", r->name);
1866 emitcode ("mov", "(%s+%d),a",
1867 regs8051[i].base, 8 * bank + regs8051[i].offset);
1868 emitcode ("dec", "%s", r->name);
1872 emitcode ("pop", "(%s+%d)",
1873 regs8051[i].base, 8 * bank + regs8051[i].offset);
1876 if (options.useXstack)
1878 emitcode ("mov", "_spx,%s", r->name);
1883 freeAsmop (NULL, aop, ic, TRUE);
1887 /*-----------------------------------------------------------------*/
1888 /* saveRBank - saves an entire register bank on the stack */
1889 /*-----------------------------------------------------------------*/
1891 saveRBank (int bank, iCode * ic, bool pushPsw)
1897 if (options.useXstack)
1901 /* Assume r0 is available for use. */
1902 r = mcs51_regWithIdx (R0_IDX);;
1907 r = getFreePtr (ic, &aop, FALSE);
1909 emitcode ("mov", "%s,_spx", r->name);
1912 for (i = 0; i < mcs51_nRegs; i++)
1914 if (options.useXstack)
1916 emitcode ("inc", "%s", r->name);
1917 emitcode ("mov", "a,(%s+%d)",
1918 regs8051[i].base, 8 * bank + regs8051[i].offset);
1919 emitcode ("movx", "@%s,a", r->name);
1922 emitcode ("push", "(%s+%d)",
1923 regs8051[i].base, 8 * bank + regs8051[i].offset);
1928 if (options.useXstack)
1930 emitcode ("mov", "a,psw");
1931 emitcode ("movx", "@%s,a", r->name);
1932 emitcode ("inc", "%s", r->name);
1933 emitcode ("mov", "_spx,%s", r->name);
1938 emitcode ("push", "psw");
1941 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1946 freeAsmop (NULL, aop, ic, TRUE);
1955 /*-----------------------------------------------------------------*/
1956 /* genSend - gen code for SEND */
1957 /*-----------------------------------------------------------------*/
1958 static void genSend(set *sendSet)
1963 for (sic = setFirstItem (_G.sendSet); sic;
1964 sic = setNextItem (_G.sendSet)) {
1965 int size, offset = 0;
1966 aopOp (IC_LEFT (sic), sic, FALSE);
1967 size = AOP_SIZE (IC_LEFT (sic));
1969 if (sic->argreg == 1) {
1971 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1973 if (strcmp (l, fReturn[offset]))
1974 emitcode ("mov", "%s,%s", fReturn[offset], l);
1980 emitcode ("mov","b1_%d,%s",rb1_count++,
1981 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1984 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1988 /*-----------------------------------------------------------------*/
1989 /* genCall - generates a call statement */
1990 /*-----------------------------------------------------------------*/
1992 genCall (iCode * ic)
1995 // bool restoreBank = FALSE;
1996 bool swapBanks = FALSE;
1998 D(emitcode("; genCall",""));
2000 dtype = operandType (IC_LEFT (ic));
2001 /* if send set is not empty the assign */
2004 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2005 genSend(reverseSet(_G.sendSet));
2007 genSend(_G.sendSet);
2013 /* if we are calling a not _naked function that is not using
2014 the same register bank then we need to save the
2015 destination registers on the stack */
2016 dtype = operandType (IC_LEFT (ic));
2017 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2018 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2019 !IFFUNC_ISISR (dtype))
2024 /* if caller saves & we have not saved then */
2030 emitcode ("mov", "psw,#0x%02x",
2031 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2035 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2036 OP_SYMBOL (IC_LEFT (ic))->rname :
2037 OP_SYMBOL (IC_LEFT (ic))->name));
2041 emitcode ("mov", "psw,#0x%02x",
2042 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2045 /* if we need assign a result value */
2046 if ((IS_ITEMP (IC_RESULT (ic)) &&
2047 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2048 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2049 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2050 IS_TRUE_SYMOP (IC_RESULT (ic)))
2054 aopOp (IC_RESULT (ic), ic, FALSE);
2057 assignResultValue (IC_RESULT (ic));
2059 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2062 /* adjust the stack for parameters if
2067 if (ic->parmBytes > 3)
2069 emitcode ("mov", "a,%s", spname);
2070 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2071 emitcode ("mov", "%s,a", spname);
2074 for (i = 0; i < ic->parmBytes; i++)
2075 emitcode ("dec", "%s", spname);
2078 /* if we hade saved some registers then unsave them */
2079 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2080 unsaveRegisters (ic);
2082 // /* if register bank was saved then pop them */
2084 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2087 /*-----------------------------------------------------------------*/
2088 /* -10l - generates a call by pointer statement */
2089 /*-----------------------------------------------------------------*/
2091 genPcall (iCode * ic)
2094 symbol *rlbl = newiTempLabel (NULL);
2095 // bool restoreBank=FALSE;
2096 bool swapBanks = FALSE;
2098 D(emitcode("; genPCall",""));
2100 /* if caller saves & we have not saved then */
2104 /* if we are calling a not _naked function that is not using
2105 the same register bank then we need to save the
2106 destination registers on the stack */
2107 dtype = operandType (IC_LEFT (ic))->next;
2108 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2109 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2110 !IFFUNC_ISISR (dtype))
2112 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2113 // restoreBank=TRUE;
2115 // need caution message to user here
2118 /* push the return address on to the stack */
2119 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2120 emitcode ("push", "acc");
2121 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2122 emitcode ("push", "acc");
2124 /* now push the calling address */
2125 aopOp (IC_LEFT (ic), ic, FALSE);
2127 pushSide (IC_LEFT (ic), FPTRSIZE);
2129 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2131 /* if send set is not empty the assign */
2134 genSend(reverseSet(_G.sendSet));
2140 emitcode ("mov", "psw,#0x%02x",
2141 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2145 emitcode ("ret", "");
2146 emitcode ("", "%05d$:", (rlbl->key + 100));
2151 emitcode ("mov", "psw,#0x%02x",
2152 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2155 /* if we need assign a result value */
2156 if ((IS_ITEMP (IC_RESULT (ic)) &&
2157 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2158 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2159 IS_TRUE_SYMOP (IC_RESULT (ic)))
2163 aopOp (IC_RESULT (ic), ic, FALSE);
2166 assignResultValue (IC_RESULT (ic));
2168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2171 /* adjust the stack for parameters if
2176 if (ic->parmBytes > 3)
2178 emitcode ("mov", "a,%s", spname);
2179 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2180 emitcode ("mov", "%s,a", spname);
2183 for (i = 0; i < ic->parmBytes; i++)
2184 emitcode ("dec", "%s", spname);
2188 // /* if register bank was saved then unsave them */
2190 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2192 /* if we hade saved some registers then
2194 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2195 unsaveRegisters (ic);
2198 /*-----------------------------------------------------------------*/
2199 /* resultRemat - result is rematerializable */
2200 /*-----------------------------------------------------------------*/
2202 resultRemat (iCode * ic)
2204 if (SKIP_IC (ic) || ic->op == IFX)
2207 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2209 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2210 if (sym->remat && !POINTER_SET (ic))
2217 #if defined(__BORLANDC__) || defined(_MSC_VER)
2218 #define STRCASECMP stricmp
2220 #define STRCASECMP strcasecmp
2223 /*-----------------------------------------------------------------*/
2224 /* inExcludeList - return 1 if the string is in exclude Reg list */
2225 /*-----------------------------------------------------------------*/
2227 inExcludeList (char *s)
2231 if (options.excludeRegs[i] &&
2232 STRCASECMP (options.excludeRegs[i], "none") == 0)
2235 for (i = 0; options.excludeRegs[i]; i++)
2237 if (options.excludeRegs[i] &&
2238 STRCASECMP (s, options.excludeRegs[i]) == 0)
2244 /*-----------------------------------------------------------------*/
2245 /* genFunction - generated code for function entry */
2246 /*-----------------------------------------------------------------*/
2248 genFunction (iCode * ic)
2252 bool switchedPSW = FALSE;
2253 int calleesaves_saved_register = -1;
2256 /* create the function header */
2257 emitcode (";", "-----------------------------------------");
2258 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2259 emitcode (";", "-----------------------------------------");
2261 emitcode ("", "%s:", sym->rname);
2262 ftype = operandType (IC_LEFT (ic));
2264 if (IFFUNC_ISNAKED(ftype))
2266 emitcode(";", "naked function: no prologue.");
2270 /* if critical function then turn interrupts off */
2271 if (IFFUNC_ISCRITICAL (ftype))
2272 emitcode ("clr", "ea");
2274 /* here we need to generate the equates for the
2275 register bank if required */
2276 if (FUNC_REGBANK (ftype) != rbank)
2280 rbank = FUNC_REGBANK (ftype);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (strcmp (regs8051[i].base, "0") == 0)
2284 emitcode ("", "%s = 0x%02x",
2286 8 * rbank + regs8051[i].offset);
2288 emitcode ("", "%s = %s + 0x%02x",
2291 8 * rbank + regs8051[i].offset);
2295 /* if this is an interrupt service routine then
2296 save acc, b, dpl, dph */
2297 if (IFFUNC_ISISR (sym->type))
2300 if (!inExcludeList ("acc"))
2301 emitcode ("push", "acc");
2302 if (!inExcludeList ("b"))
2303 emitcode ("push", "b");
2304 if (!inExcludeList ("dpl"))
2305 emitcode ("push", "dpl");
2306 if (!inExcludeList ("dph"))
2307 emitcode ("push", "dph");
2308 /* if this isr has no bank i.e. is going to
2309 run with bank 0 , then we need to save more
2311 if (!FUNC_REGBANK (sym->type))
2314 /* if this function does not call any other
2315 function then we can be economical and
2316 save only those registers that are used */
2317 if (!IFFUNC_HASFCALL(sym->type))
2321 /* if any registers used */
2324 /* save the registers used */
2325 for (i = 0; i < sym->regsUsed->size; i++)
2327 if (bitVectBitValue (sym->regsUsed, i) ||
2328 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2329 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2337 /* this function has a function call cannot
2338 determines register usage so we will have to push the
2340 saveRBank (0, ic, FALSE);
2341 if (options.parms_in_bank1) {
2343 for (i=0; i < 8 ; i++ ) {
2344 emitcode ("push","%s",rb1regs[i]);
2351 /* This ISR uses a non-zero bank.
2353 * We assume that the bank is available for our
2356 * However, if this ISR calls a function which uses some
2357 * other bank, we must save that bank entirely.
2359 unsigned long banksToSave = 0;
2361 if (IFFUNC_HASFCALL(sym->type))
2364 #define MAX_REGISTER_BANKS 4
2369 for (i = ic; i; i = i->next)
2371 if (i->op == ENDFUNCTION)
2373 /* we got to the end OK. */
2381 dtype = operandType (IC_LEFT(i));
2383 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2385 /* Mark this bank for saving. */
2386 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2388 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2392 banksToSave |= (1 << FUNC_REGBANK(dtype));
2395 /* And note that we don't need to do it in
2403 /* This is a mess; we have no idea what
2404 * register bank the called function might
2407 * The only thing I can think of to do is
2408 * throw a warning and hope.
2410 werror(W_FUNCPTR_IN_USING_ISR);
2414 if (banksToSave && options.useXstack)
2416 /* Since we aren't passing it an ic,
2417 * saveRBank will assume r0 is available to abuse.
2419 * So switch to our (trashable) bank now, so
2420 * the caller's R0 isn't trashed.
2422 emitcode ("push", "psw");
2423 emitcode ("mov", "psw,#0x%02x",
2424 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2428 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2430 if (banksToSave & (1 << ix))
2432 saveRBank(ix, NULL, FALSE);
2436 // jwk: this needs a closer look
2437 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2442 /* if callee-save to be used for this function
2443 then save the registers being used in this function */
2444 if (IFFUNC_CALLEESAVES(sym->type))
2448 /* if any registers used */
2451 /* save the registers used */
2452 for (i = 0; i < sym->regsUsed->size; i++)
2454 if (bitVectBitValue (sym->regsUsed, i) ||
2455 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2457 /* remember one saved register for later usage */
2458 if (calleesaves_saved_register < 0)
2459 calleesaves_saved_register = i;
2460 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2468 /* set the register bank to the desired value */
2469 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2472 emitcode ("push", "psw");
2473 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2476 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2479 if (options.useXstack)
2481 emitcode ("mov", "r0,%s", spname);
2482 emitcode ("mov", "a,_bp");
2483 emitcode ("movx", "@r0,a");
2484 emitcode ("inc", "%s", spname);
2488 /* set up the stack */
2489 emitcode ("push", "_bp"); /* save the callers stack */
2491 emitcode ("mov", "_bp,%s", spname);
2494 /* adjust the stack for the function */
2500 werror (W_STACK_OVERFLOW, sym->name);
2502 if (i > 3 && sym->recvSize < 4)
2505 emitcode ("mov", "a,sp");
2506 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2507 emitcode ("mov", "sp,a");
2512 if (IFFUNC_CALLEESAVES(sym->type))
2514 /* if it's a callee-saves function we need a saved register */
2515 if (calleesaves_saved_register >= 0)
2517 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2518 emitcode ("mov", "a,sp");
2519 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2520 emitcode ("mov", "sp,a");
2521 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2524 /* do it the hard way */
2526 emitcode ("inc", "sp");
2530 /* not callee-saves, we can clobber r0 */
2531 emitcode ("mov", "r0,a");
2532 emitcode ("mov", "a,sp");
2533 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2534 emitcode ("mov", "sp,a");
2535 emitcode ("mov", "a,r0");
2540 emitcode ("inc", "sp");
2546 emitcode ("mov", "a,_spx");
2547 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2548 emitcode ("mov", "_spx,a");
2553 /*-----------------------------------------------------------------*/
2554 /* genEndFunction - generates epilogue for functions */
2555 /*-----------------------------------------------------------------*/
2557 genEndFunction (iCode * ic)
2559 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2561 if (IFFUNC_ISNAKED(sym->type))
2563 emitcode(";", "naked function: no epilogue.");
2567 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2569 emitcode ("mov", "%s,_bp", spname);
2572 /* if use external stack but some variables were
2573 added to the local stack then decrement the
2575 if (options.useXstack && sym->stack)
2577 emitcode ("mov", "a,sp");
2578 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2579 emitcode ("mov", "sp,a");
2583 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2585 if (options.useXstack)
2587 emitcode ("mov", "r0,%s", spname);
2588 emitcode ("movx", "a,@r0");
2589 emitcode ("mov", "_bp,a");
2590 emitcode ("dec", "%s", spname);
2594 emitcode ("pop", "_bp");
2598 /* restore the register bank */
2599 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2601 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2602 || !options.useXstack)
2604 /* Special case of ISR using non-zero bank with useXstack
2607 emitcode ("pop", "psw");
2611 if (IFFUNC_ISISR (sym->type))
2614 /* now we need to restore the registers */
2615 /* if this isr has no bank i.e. is going to
2616 run with bank 0 , then we need to save more
2618 if (!FUNC_REGBANK (sym->type))
2620 /* if this function does not call any other
2621 function then we can be economical and
2622 save only those registers that are used */
2623 if (!IFFUNC_HASFCALL(sym->type))
2627 /* if any registers used */
2630 /* save the registers used */
2631 for (i = sym->regsUsed->size; i >= 0; i--)
2633 if (bitVectBitValue (sym->regsUsed, i) ||
2634 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2635 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2642 if (options.parms_in_bank1) {
2644 for (i = 7 ; i >= 0 ; i-- ) {
2645 emitcode ("pop","%s",rb1regs[i]);
2648 /* this function has a function call cannot
2649 determines register usage so we will have to pop the
2651 unsaveRBank (0, ic, FALSE);
2656 /* This ISR uses a non-zero bank.
2658 * Restore any register banks saved by genFunction
2661 // jwk: this needs a closer look
2662 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2665 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2667 if (savedBanks & (1 << ix))
2669 unsaveRBank(ix, NULL, FALSE);
2673 if (options.useXstack)
2675 /* Restore bank AFTER calling unsaveRBank,
2676 * since it can trash r0.
2678 emitcode ("pop", "psw");
2682 if (!inExcludeList ("dph"))
2683 emitcode ("pop", "dph");
2684 if (!inExcludeList ("dpl"))
2685 emitcode ("pop", "dpl");
2686 if (!inExcludeList ("b"))
2687 emitcode ("pop", "b");
2688 if (!inExcludeList ("acc"))
2689 emitcode ("pop", "acc");
2691 if (IFFUNC_ISCRITICAL (sym->type))
2692 emitcode ("setb", "ea");
2694 /* if debug then send end of function */
2695 if (options.debug && currFunc)
2698 emitcode ("", "C$%s$%d$%d$%d ==.",
2699 FileBaseName (ic->filename), currFunc->lastLine,
2700 ic->level, ic->block);
2701 if (IS_STATIC (currFunc->etype))
2702 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2704 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2708 emitcode ("reti", "");
2712 if (IFFUNC_ISCRITICAL (sym->type))
2713 emitcode ("setb", "ea");
2715 if (IFFUNC_CALLEESAVES(sym->type))
2719 /* if any registers used */
2722 /* save the registers used */
2723 for (i = sym->regsUsed->size; i >= 0; i--)
2725 if (bitVectBitValue (sym->regsUsed, i) ||
2726 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2727 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2733 /* if debug then send end of function */
2734 if (options.debug && currFunc)
2737 emitcode ("", "C$%s$%d$%d$%d ==.",
2738 FileBaseName (ic->filename), currFunc->lastLine,
2739 ic->level, ic->block);
2740 if (IS_STATIC (currFunc->etype))
2741 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2743 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2747 emitcode ("ret", "");
2752 /*-----------------------------------------------------------------*/
2753 /* genRet - generate code for return statement */
2754 /*-----------------------------------------------------------------*/
2758 int size, offset = 0, pushed = 0;
2760 D(emitcode ("; genRet",""));
2762 /* if we have no return value then
2763 just generate the "ret" */
2767 /* we have something to return then
2768 move the return value into place */
2769 aopOp (IC_LEFT (ic), ic, FALSE);
2770 size = AOP_SIZE (IC_LEFT (ic));
2775 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2778 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2780 emitcode ("push", "%s", l);
2785 l = aopGet (AOP (IC_LEFT (ic)), offset,
2787 if (strcmp (fReturn[offset], l))
2788 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2797 if (strcmp (fReturn[pushed], "a"))
2798 emitcode ("pop", fReturn[pushed]);
2800 emitcode ("pop", "acc");
2803 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2806 /* generate a jump to the return label
2807 if the next is not the return statement */
2808 if (!(ic->next && ic->next->op == LABEL &&
2809 IC_LABEL (ic->next) == returnLabel))
2811 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2815 /*-----------------------------------------------------------------*/
2816 /* genLabel - generates a label */
2817 /*-----------------------------------------------------------------*/
2819 genLabel (iCode * ic)
2821 /* special case never generate */
2822 if (IC_LABEL (ic) == entryLabel)
2825 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2828 /*-----------------------------------------------------------------*/
2829 /* genGoto - generates a ljmp */
2830 /*-----------------------------------------------------------------*/
2832 genGoto (iCode * ic)
2834 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2837 /*-----------------------------------------------------------------*/
2838 /* findLabelBackwards: walks back through the iCode chain looking */
2839 /* for the given label. Returns number of iCode instructions */
2840 /* between that label and given ic. */
2841 /* Returns zero if label not found. */
2842 /*-----------------------------------------------------------------*/
2844 findLabelBackwards (iCode * ic, int key)
2853 /* If we have any pushes or pops, we cannot predict the distance.
2854 I don't like this at all, this should be dealt with in the
2856 if (ic->op == IPUSH || ic->op == IPOP) {
2860 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2869 /*-----------------------------------------------------------------*/
2870 /* genPlusIncr :- does addition with increment if possible */
2871 /*-----------------------------------------------------------------*/
2873 genPlusIncr (iCode * ic)
2875 unsigned int icount;
2876 unsigned int size = getDataSize (IC_RESULT (ic));
2878 /* will try to generate an increment */
2879 /* if the right side is not a literal
2881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2884 /* if the literal value of the right hand side
2885 is greater than 4 then it is not worth it */
2886 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2889 D(emitcode ("; genPlusIncr",""));
2891 /* if increment 16 bits in register */
2892 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2893 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2901 /* If the next instruction is a goto and the goto target
2902 * is < 10 instructions previous to this, we can generate
2903 * jumps straight to that target.
2905 if (ic->next && ic->next->op == GOTO
2906 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2907 && labelRange <= 10)
2909 emitcode (";", "tail increment optimized");
2910 tlbl = IC_LABEL (ic->next);
2915 tlbl = newiTempLabel (NULL);
2918 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2920 IS_AOP_PREG (IC_RESULT (ic)))
2921 emitcode ("cjne", "%s,#0x00,%05d$",
2922 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2926 emitcode ("clr", "a");
2927 emitcode ("cjne", "a,%s,%05d$",
2928 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2932 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2936 IS_AOP_PREG (IC_RESULT (ic)))
2937 emitcode ("cjne", "%s,#0x00,%05d$",
2938 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2941 emitcode ("cjne", "a,%s,%05d$",
2942 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2945 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2949 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2950 IS_AOP_PREG (IC_RESULT (ic)))
2951 emitcode ("cjne", "%s,#0x00,%05d$",
2952 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2956 emitcode ("cjne", "a,%s,%05d$",
2957 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2960 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2965 emitcode ("", "%05d$:", tlbl->key + 100);
2970 /* if the sizes are greater than 1 then we cannot */
2971 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2972 AOP_SIZE (IC_LEFT (ic)) > 1)
2975 /* we can if the aops of the left & result match or
2976 if they are in registers and the registers are the
2978 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2983 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2984 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2985 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2991 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3000 /*-----------------------------------------------------------------*/
3001 /* outBitAcc - output a bit in acc */
3002 /*-----------------------------------------------------------------*/
3004 outBitAcc (operand * result)
3006 symbol *tlbl = newiTempLabel (NULL);
3007 /* if the result is a bit */
3008 if (AOP_TYPE (result) == AOP_CRY)
3010 aopPut (AOP (result), "a", 0);
3014 emitcode ("jz", "%05d$", tlbl->key + 100);
3015 emitcode ("mov", "a,%s", one);
3016 emitcode ("", "%05d$:", tlbl->key + 100);
3021 /*-----------------------------------------------------------------*/
3022 /* genPlusBits - generates code for addition of two bits */
3023 /*-----------------------------------------------------------------*/
3025 genPlusBits (iCode * ic)
3027 D(emitcode ("; genPlusBits",""));
3029 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3031 symbol *lbl = newiTempLabel (NULL);
3032 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3033 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3034 emitcode ("cpl", "c");
3035 emitcode ("", "%05d$:", (lbl->key + 100));
3036 outBitC (IC_RESULT (ic));
3040 emitcode ("clr", "a");
3041 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3042 emitcode ("rlc", "a");
3043 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3044 emitcode ("addc", "a,#0x00");
3045 outAcc (IC_RESULT (ic));
3050 /* This is the original version of this code.
3052 * This is being kept around for reference,
3053 * because I am not entirely sure I got it right...
3056 adjustArithmeticResult (iCode * ic)
3058 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3059 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3060 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3061 aopPut (AOP (IC_RESULT (ic)),
3062 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3065 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3066 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3067 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3068 aopPut (AOP (IC_RESULT (ic)),
3069 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3072 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3073 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3074 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3075 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3076 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3079 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3080 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3084 /* This is the pure and virtuous version of this code.
3085 * I'm pretty certain it's right, but not enough to toss the old
3089 adjustArithmeticResult (iCode * ic)
3091 if (opIsGptr (IC_RESULT (ic)) &&
3092 opIsGptr (IC_LEFT (ic)) &&
3093 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3095 aopPut (AOP (IC_RESULT (ic)),
3096 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3100 if (opIsGptr (IC_RESULT (ic)) &&
3101 opIsGptr (IC_RIGHT (ic)) &&
3102 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3104 aopPut (AOP (IC_RESULT (ic)),
3105 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3109 if (opIsGptr (IC_RESULT (ic)) &&
3110 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3111 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3112 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3113 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3116 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3117 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3122 /*-----------------------------------------------------------------*/
3123 /* genPlus - generates code for addition */
3124 /*-----------------------------------------------------------------*/
3126 genPlus (iCode * ic)
3128 int size, offset = 0;
3130 asmop *leftOp, *rightOp;
3132 /* special cases :- */
3134 D(emitcode ("; genPlus",""));
3136 aopOp (IC_LEFT (ic), ic, FALSE);
3137 aopOp (IC_RIGHT (ic), ic, FALSE);
3138 aopOp (IC_RESULT (ic), ic, TRUE);
3140 /* if literal, literal on the right or
3141 if left requires ACC or right is already
3143 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3144 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3145 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3147 operand *t = IC_RIGHT (ic);
3148 IC_RIGHT (ic) = IC_LEFT (ic);
3152 /* if both left & right are in bit
3154 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3155 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3161 /* if left in bit space & right literal */
3162 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3163 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3165 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3166 /* if result in bit space */
3167 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3169 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3170 emitcode ("cpl", "c");
3171 outBitC (IC_RESULT (ic));
3175 size = getDataSize (IC_RESULT (ic));
3178 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3179 emitcode ("addc", "a,#00");
3180 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3186 /* if I can do an increment instead
3187 of add then GOOD for ME */
3188 if (genPlusIncr (ic) == TRUE)
3191 size = getDataSize (IC_RESULT (ic));
3193 leftOp = AOP(IC_LEFT(ic));
3194 rightOp = AOP(IC_RIGHT(ic));
3199 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3201 emitcode("mov", "b,a");
3202 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3203 emitcode("xch", "a,b");
3204 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3205 emitcode (add, "a,b");
3207 else if (aopGetUsesAcc (leftOp, offset))
3209 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3210 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3214 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3215 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3217 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3218 add = "addc"; /* further adds must propagate carry */
3221 adjustArithmeticResult (ic);
3224 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3225 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3229 /*-----------------------------------------------------------------*/
3230 /* genMinusDec :- does subtraction with deccrement if possible */
3231 /*-----------------------------------------------------------------*/
3233 genMinusDec (iCode * ic)
3235 unsigned int icount;
3236 unsigned int size = getDataSize (IC_RESULT (ic));
3238 /* will try to generate an increment */
3239 /* if the right side is not a literal
3241 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3244 /* if the literal value of the right hand side
3245 is greater than 4 then it is not worth it */
3246 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3249 D(emitcode ("; genMinusDec",""));
3251 /* if decrement 16 bits in register */
3252 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3261 /* If the next instruction is a goto and the goto target
3262 * is <= 10 instructions previous to this, we can generate
3263 * jumps straight to that target.
3265 if (ic->next && ic->next->op == GOTO
3266 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3267 && labelRange <= 10)
3269 emitcode (";", "tail decrement optimized");
3270 tlbl = IC_LABEL (ic->next);
3275 tlbl = newiTempLabel (NULL);
3279 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3281 IS_AOP_PREG (IC_RESULT (ic)))
3282 emitcode ("cjne", "%s,#0xff,%05d$"
3283 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3287 emitcode ("mov", "a,#0xff");
3288 emitcode ("cjne", "a,%s,%05d$"
3289 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3292 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3296 IS_AOP_PREG (IC_RESULT (ic)))
3297 emitcode ("cjne", "%s,#0xff,%05d$"
3298 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3302 emitcode ("cjne", "a,%s,%05d$"
3303 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3306 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3310 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3311 IS_AOP_PREG (IC_RESULT (ic)))
3312 emitcode ("cjne", "%s,#0xff,%05d$"
3313 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3317 emitcode ("cjne", "a,%s,%05d$"
3318 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3321 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3325 emitcode ("", "%05d$:", tlbl->key + 100);
3330 /* if the sizes are greater than 1 then we cannot */
3331 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3332 AOP_SIZE (IC_LEFT (ic)) > 1)
3335 /* we can if the aops of the left & result match or
3336 if they are in registers and the registers are the
3338 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3342 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3350 /*-----------------------------------------------------------------*/
3351 /* addSign - complete with sign */
3352 /*-----------------------------------------------------------------*/
3354 addSign (operand * result, int offset, int sign)
3356 int size = (getDataSize (result) - offset);
3361 emitcode ("rlc", "a");
3362 emitcode ("subb", "a,acc");
3364 aopPut (AOP (result), "a", offset++);
3368 aopPut (AOP (result), zero, offset++);
3372 /*-----------------------------------------------------------------*/
3373 /* genMinusBits - generates code for subtraction of two bits */
3374 /*-----------------------------------------------------------------*/
3376 genMinusBits (iCode * ic)
3378 symbol *lbl = newiTempLabel (NULL);
3380 D(emitcode ("; genMinusBits",""));
3382 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3384 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3385 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3386 emitcode ("cpl", "c");
3387 emitcode ("", "%05d$:", (lbl->key + 100));
3388 outBitC (IC_RESULT (ic));
3392 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3393 emitcode ("subb", "a,acc");
3394 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3395 emitcode ("inc", "a");
3396 emitcode ("", "%05d$:", (lbl->key + 100));
3397 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3398 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3402 /*-----------------------------------------------------------------*/
3403 /* genMinus - generates code for subtraction */
3404 /*-----------------------------------------------------------------*/
3406 genMinus (iCode * ic)
3408 int size, offset = 0;
3410 D(emitcode ("; genMinus",""));
3412 aopOp (IC_LEFT (ic), ic, FALSE);
3413 aopOp (IC_RIGHT (ic), ic, FALSE);
3414 aopOp (IC_RESULT (ic), ic, TRUE);
3416 /* special cases :- */
3417 /* if both left & right are in bit space */
3418 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3419 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3425 /* if I can do an decrement instead
3426 of subtract then GOOD for ME */
3427 if (genMinusDec (ic) == TRUE)
3430 size = getDataSize (IC_RESULT (ic));
3432 /* if literal, add a,#-lit, else normal subb */
3433 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3435 unsigned long lit = 0L;
3437 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3442 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3443 /* first add without previous c */
3445 if (!size && lit==-1) {
3446 emitcode ("dec", "a");
3448 emitcode ("add", "a,#0x%02x",
3449 (unsigned int) (lit & 0x0FFL));
3452 emitcode ("addc", "a,#0x%02x",
3453 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3455 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3460 asmop *leftOp, *rightOp;
3462 leftOp = AOP(IC_LEFT(ic));
3463 rightOp = AOP(IC_RIGHT(ic));
3467 if (aopGetUsesAcc(rightOp, offset)) {
3468 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3469 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3471 emitcode( "cpl", "c");
3473 emitcode( "setb", "c");
3475 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3476 emitcode("cpl", "a");
3478 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3481 emitcode ("subb", "a,%s",
3482 aopGet(rightOp, offset, FALSE, TRUE));
3485 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3490 adjustArithmeticResult (ic);
3493 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3494 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3495 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3499 /*-----------------------------------------------------------------*/
3500 /* genMultbits :- multiplication of bits */
3501 /*-----------------------------------------------------------------*/
3503 genMultbits (operand * left,
3507 D(emitcode ("; genMultbits",""));
3509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3510 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3515 /*-----------------------------------------------------------------*/
3516 /* genMultOneByte : 8*8=8/16 bit multiplication */
3517 /*-----------------------------------------------------------------*/
3519 genMultOneByte (operand * left,
3523 sym_link *opetype = operandType (result);
3525 int size=AOP_SIZE(result);
3527 D(emitcode ("; genMultOneByte",""));
3529 if (size<1 || size>2) {
3530 // this should never happen
3531 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3532 AOP_SIZE(result), __FILE__, lineno);
3536 /* (if two literals: the value is computed before) */
3537 /* if one literal, literal on the right */
3538 if (AOP_TYPE (left) == AOP_LIT)
3543 //emitcode (";", "swapped left and right");
3546 if (SPEC_USIGN(opetype)
3547 // ignore the sign of left and right, what else can we do?
3548 || (SPEC_USIGN(operandType(left)) &&
3549 SPEC_USIGN(operandType(right)))) {
3550 // just an unsigned 8*8=8/16 multiply
3551 //emitcode (";","unsigned");
3552 // TODO: check for accumulator clash between left & right aops?
3553 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3554 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3555 emitcode ("mul", "ab");
3556 aopPut (AOP (result), "a", 0);
3558 aopPut (AOP (result), "b", 1);
3563 // we have to do a signed multiply
3565 //emitcode (";", "signed");
3566 emitcode ("clr", "F0"); // reset sign flag
3567 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3569 lbl=newiTempLabel(NULL);
3570 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3571 // left side is negative, 8-bit two's complement, this fails for -128
3572 emitcode ("setb", "F0"); // set sign flag
3573 emitcode ("cpl", "a");
3574 emitcode ("inc", "a");
3576 emitcode ("", "%05d$:", lbl->key+100);
3579 if (AOP_TYPE(right)==AOP_LIT) {
3580 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3581 /* AND literal negative */
3583 emitcode ("cpl", "F0"); // complement sign flag
3584 emitcode ("mov", "b,#0x%02x", -val);
3586 emitcode ("mov", "b,#0x%02x", val);
3589 lbl=newiTempLabel(NULL);
3590 emitcode ("mov", "b,a");
3591 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3592 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3593 // right side is negative, 8-bit two's complement
3594 emitcode ("cpl", "F0"); // complement sign flag
3595 emitcode ("cpl", "a");
3596 emitcode ("inc", "a");
3597 emitcode ("", "%05d$:", lbl->key+100);
3599 emitcode ("mul", "ab");
3601 lbl=newiTempLabel(NULL);
3602 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3603 // only ONE op was negative, we have to do a 8/16-bit two's complement
3604 emitcode ("cpl", "a"); // lsb
3606 emitcode ("inc", "a");
3608 emitcode ("add", "a,#1");
3609 emitcode ("xch", "a,b");
3610 emitcode ("cpl", "a"); // msb
3611 emitcode ("addc", "a,#0");
3612 emitcode ("xch", "a,b");
3615 emitcode ("", "%05d$:", lbl->key+100);
3616 aopPut (AOP (result), "a", 0);
3618 aopPut (AOP (result), "b", 1);
3622 /*-----------------------------------------------------------------*/
3623 /* genMult - generates code for multiplication */
3624 /*-----------------------------------------------------------------*/
3626 genMult (iCode * ic)
3628 operand *left = IC_LEFT (ic);
3629 operand *right = IC_RIGHT (ic);
3630 operand *result = IC_RESULT (ic);
3632 D(emitcode ("; genMult",""));
3634 /* assign the amsops */
3635 aopOp (left, ic, FALSE);
3636 aopOp (right, ic, FALSE);
3637 aopOp (result, ic, TRUE);
3639 /* special cases first */
3641 if (AOP_TYPE (left) == AOP_CRY &&
3642 AOP_TYPE (right) == AOP_CRY)
3644 genMultbits (left, right, result);
3648 /* if both are of size == 1 */
3649 #if 0 // one of them can be a sloc shared with the result
3650 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3652 if (getSize(operandType(left)) == 1 &&
3653 getSize(operandType(right)) == 1)
3656 genMultOneByte (left, right, result);
3660 /* should have been converted to function call */
3661 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3662 getSize(OP_SYMBOL(right)->type));
3666 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (result, NULL, ic, TRUE);
3671 /*-----------------------------------------------------------------*/
3672 /* genDivbits :- division of bits */
3673 /*-----------------------------------------------------------------*/
3675 genDivbits (operand * left,
3682 D(emitcode ("; genDivbits",""));
3684 /* the result must be bit */
3685 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3686 l = aopGet (AOP (left), 0, FALSE, FALSE);
3690 emitcode ("div", "ab");
3691 emitcode ("rrc", "a");
3692 aopPut (AOP (result), "c", 0);
3695 /*-----------------------------------------------------------------*/
3696 /* genDivOneByte : 8 bit division */
3697 /*-----------------------------------------------------------------*/
3699 genDivOneByte (operand * left,
3703 sym_link *opetype = operandType (result);
3708 D(emitcode ("; genDivOneByte",""));
3710 size = AOP_SIZE (result) - 1;
3712 /* signed or unsigned */
3713 if (SPEC_USIGN (opetype))
3715 /* unsigned is easy */
3716 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3717 l = aopGet (AOP (left), 0, FALSE, FALSE);
3719 emitcode ("div", "ab");
3720 aopPut (AOP (result), "a", 0);
3722 aopPut (AOP (result), zero, offset++);
3726 /* signed is a little bit more difficult */
3728 /* save the signs of the operands */
3729 l = aopGet (AOP (left), 0, FALSE, FALSE);
3731 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3732 emitcode ("push", "acc"); /* save it on the stack */
3734 /* now sign adjust for both left & right */
3735 l = aopGet (AOP (right), 0, FALSE, FALSE);
3737 lbl = newiTempLabel (NULL);
3738 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3739 emitcode ("cpl", "a");
3740 emitcode ("inc", "a");
3741 emitcode ("", "%05d$:", (lbl->key + 100));
3742 emitcode ("mov", "b,a");
3744 /* sign adjust left side */
3745 l = aopGet (AOP (left), 0, FALSE, FALSE);
3748 lbl = newiTempLabel (NULL);
3749 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3750 emitcode ("cpl", "a");
3751 emitcode ("inc", "a");
3752 emitcode ("", "%05d$:", (lbl->key + 100));
3754 /* now the division */
3755 emitcode ("div", "ab");
3756 /* we are interested in the lower order
3758 emitcode ("mov", "b,a");
3759 lbl = newiTempLabel (NULL);
3760 emitcode ("pop", "acc");
3761 /* if there was an over flow we don't
3762 adjust the sign of the result */
3763 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3764 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3766 emitcode ("clr", "a");
3767 emitcode ("subb", "a,b");
3768 emitcode ("mov", "b,a");
3769 emitcode ("", "%05d$:", (lbl->key + 100));
3771 /* now we are done */
3772 aopPut (AOP (result), "b", 0);
3775 emitcode ("mov", "c,b.7");
3776 emitcode ("subb", "a,acc");
3779 aopPut (AOP (result), "a", offset++);
3783 /*-----------------------------------------------------------------*/
3784 /* genDiv - generates code for division */
3785 /*-----------------------------------------------------------------*/
3789 operand *left = IC_LEFT (ic);
3790 operand *right = IC_RIGHT (ic);
3791 operand *result = IC_RESULT (ic);
3793 D(emitcode ("; genDiv",""));
3795 /* assign the amsops */
3796 aopOp (left, ic, FALSE);
3797 aopOp (right, ic, FALSE);
3798 aopOp (result, ic, TRUE);
3800 /* special cases first */
3802 if (AOP_TYPE (left) == AOP_CRY &&
3803 AOP_TYPE (right) == AOP_CRY)
3805 genDivbits (left, right, result);
3809 /* if both are of size == 1 */
3810 if (AOP_SIZE (left) == 1 &&
3811 AOP_SIZE (right) == 1)
3813 genDivOneByte (left, right, result);
3817 /* should have been converted to function call */
3820 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3821 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3822 freeAsmop (result, NULL, ic, TRUE);
3825 /*-----------------------------------------------------------------*/
3826 /* genModbits :- modulus of bits */
3827 /*-----------------------------------------------------------------*/
3829 genModbits (operand * left,
3836 D(emitcode ("; genModbits",""));
3838 /* the result must be bit */
3839 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3840 l = aopGet (AOP (left), 0, FALSE, FALSE);
3844 emitcode ("div", "ab");
3845 emitcode ("mov", "a,b");
3846 emitcode ("rrc", "a");
3847 aopPut (AOP (result), "c", 0);
3850 /*-----------------------------------------------------------------*/
3851 /* genModOneByte : 8 bit modulus */
3852 /*-----------------------------------------------------------------*/
3854 genModOneByte (operand * left,
3858 sym_link *opetype = operandType (result);
3862 D(emitcode ("; genModOneByte",""));
3864 /* signed or unsigned */
3865 if (SPEC_USIGN (opetype))
3867 /* unsigned is easy */
3868 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3869 l = aopGet (AOP (left), 0, FALSE, FALSE);
3871 emitcode ("div", "ab");
3872 aopPut (AOP (result), "b", 0);
3876 /* signed is a little bit more difficult */
3878 /* save the signs of the operands */
3879 l = aopGet (AOP (left), 0, FALSE, FALSE);
3882 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3883 emitcode ("push", "acc"); /* save it on the stack */
3885 /* now sign adjust for both left & right */
3886 l = aopGet (AOP (right), 0, FALSE, FALSE);
3889 lbl = newiTempLabel (NULL);
3890 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3891 emitcode ("cpl", "a");
3892 emitcode ("inc", "a");
3893 emitcode ("", "%05d$:", (lbl->key + 100));
3894 emitcode ("mov", "b,a");
3896 /* sign adjust left side */
3897 l = aopGet (AOP (left), 0, FALSE, FALSE);
3900 lbl = newiTempLabel (NULL);
3901 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3902 emitcode ("cpl", "a");
3903 emitcode ("inc", "a");
3904 emitcode ("", "%05d$:", (lbl->key + 100));
3906 /* now the multiplication */
3907 emitcode ("div", "ab");
3908 /* we are interested in the lower order
3910 lbl = newiTempLabel (NULL);
3911 emitcode ("pop", "acc");
3912 /* if there was an over flow we don't
3913 adjust the sign of the result */
3914 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3915 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3917 emitcode ("clr", "a");
3918 emitcode ("subb", "a,b");
3919 emitcode ("mov", "b,a");
3920 emitcode ("", "%05d$:", (lbl->key + 100));
3922 /* now we are done */
3923 aopPut (AOP (result), "b", 0);
3927 /*-----------------------------------------------------------------*/
3928 /* genMod - generates code for division */
3929 /*-----------------------------------------------------------------*/
3933 operand *left = IC_LEFT (ic);
3934 operand *right = IC_RIGHT (ic);
3935 operand *result = IC_RESULT (ic);
3937 D(emitcode ("; genMod",""));
3939 /* assign the amsops */
3940 aopOp (left, ic, FALSE);
3941 aopOp (right, ic, FALSE);
3942 aopOp (result, ic, TRUE);
3944 /* special cases first */
3946 if (AOP_TYPE (left) == AOP_CRY &&
3947 AOP_TYPE (right) == AOP_CRY)
3949 genModbits (left, right, result);
3953 /* if both are of size == 1 */
3954 if (AOP_SIZE (left) == 1 &&
3955 AOP_SIZE (right) == 1)
3957 genModOneByte (left, right, result);
3961 /* should have been converted to function call */
3965 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (result, NULL, ic, TRUE);
3970 /*-----------------------------------------------------------------*/
3971 /* genIfxJump :- will create a jump depending on the ifx */
3972 /*-----------------------------------------------------------------*/
3974 genIfxJump (iCode * ic, char *jval)
3977 symbol *tlbl = newiTempLabel (NULL);
3980 D(emitcode ("; genIfxJump",""));
3982 /* if true label then we jump if condition
3986 jlbl = IC_TRUE (ic);
3987 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3988 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3992 /* false label is present */
3993 jlbl = IC_FALSE (ic);
3994 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3995 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3997 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3998 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4000 emitcode (inst, "%05d$", tlbl->key + 100);
4001 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4002 emitcode ("", "%05d$:", tlbl->key + 100);
4004 /* mark the icode as generated */
4008 /*-----------------------------------------------------------------*/
4009 /* genCmp :- greater or less than comparison */
4010 /*-----------------------------------------------------------------*/
4012 genCmp (operand * left, operand * right,
4013 operand * result, iCode * ifx, int sign, iCode *ic)
4015 int size, offset = 0;
4016 unsigned long lit = 0L;
4018 D(emitcode ("; genCmp",""));
4020 /* if left & right are bit variables */
4021 if (AOP_TYPE (left) == AOP_CRY &&
4022 AOP_TYPE (right) == AOP_CRY)
4024 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4025 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4029 /* subtract right from left if at the
4030 end the carry flag is set then we know that
4031 left is greater than right */
4032 size = max (AOP_SIZE (left), AOP_SIZE (right));
4034 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4035 if ((size == 1) && !sign &&
4036 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4038 symbol *lbl = newiTempLabel (NULL);
4039 emitcode ("cjne", "%s,%s,%05d$",
4040 aopGet (AOP (left), offset, FALSE, FALSE),
4041 aopGet (AOP (right), offset, FALSE, FALSE),
4043 emitcode ("", "%05d$:", lbl->key + 100);
4047 if (AOP_TYPE (right) == AOP_LIT)
4049 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4050 /* optimize if(x < 0) or if(x >= 0) */
4059 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4060 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4062 genIfxJump (ifx, "acc.7");
4066 emitcode ("rlc", "a");
4074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4075 if (sign && size == 0)
4077 emitcode ("xrl", "a,#0x80");
4078 if (AOP_TYPE (right) == AOP_LIT)
4080 unsigned long lit = (unsigned long)
4081 floatFromVal (AOP (right)->aopu.aop_lit);
4082 emitcode ("subb", "a,#0x%02x",
4083 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4087 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4088 emitcode ("xrl", "b,#0x80");
4089 emitcode ("subb", "a,b");
4093 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4099 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4100 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4107 /* if the result is used in the next
4108 ifx conditional branch then generate
4109 code a little differently */
4111 genIfxJump (ifx, "c");
4114 /* leave the result in acc */
4118 /*-----------------------------------------------------------------*/
4119 /* genCmpGt :- greater than comparison */
4120 /*-----------------------------------------------------------------*/
4122 genCmpGt (iCode * ic, iCode * ifx)
4124 operand *left, *right, *result;
4125 sym_link *letype, *retype;
4128 D(emitcode ("; genCmpGt",""));
4130 left = IC_LEFT (ic);
4131 right = IC_RIGHT (ic);
4132 result = IC_RESULT (ic);
4134 letype = getSpec (operandType (left));
4135 retype = getSpec (operandType (right));
4136 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4137 /* assign the amsops */
4138 aopOp (left, ic, FALSE);
4139 aopOp (right, ic, FALSE);
4140 aopOp (result, ic, TRUE);
4142 genCmp (right, left, result, ifx, sign,ic);
4144 freeAsmop (result, NULL, ic, TRUE);
4147 /*-----------------------------------------------------------------*/
4148 /* genCmpLt - less than comparisons */
4149 /*-----------------------------------------------------------------*/
4151 genCmpLt (iCode * ic, iCode * ifx)
4153 operand *left, *right, *result;
4154 sym_link *letype, *retype;
4157 D(emitcode ("; genCmpLt",""));
4159 left = IC_LEFT (ic);
4160 right = IC_RIGHT (ic);
4161 result = IC_RESULT (ic);
4163 letype = getSpec (operandType (left));
4164 retype = getSpec (operandType (right));
4165 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4167 /* assign the amsops */
4168 aopOp (left, ic, FALSE);
4169 aopOp (right, ic, FALSE);
4170 aopOp (result, ic, TRUE);
4172 genCmp (left, right, result, ifx, sign,ic);
4174 freeAsmop (result, NULL, ic, TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* gencjneshort - compare and jump if not equal */
4179 /*-----------------------------------------------------------------*/
4181 gencjneshort (operand * left, operand * right, symbol * lbl)
4183 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4185 unsigned long lit = 0L;
4187 /* if the left side is a literal or
4188 if the right is in a pointer register and left
4190 if ((AOP_TYPE (left) == AOP_LIT) ||
4191 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4197 if (AOP_TYPE (right) == AOP_LIT)
4198 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4200 /* if the right side is a literal then anything goes */
4201 if (AOP_TYPE (right) == AOP_LIT &&
4202 AOP_TYPE (left) != AOP_DIR)
4206 emitcode ("cjne", "%s,%s,%05d$",
4207 aopGet (AOP (left), offset, FALSE, FALSE),
4208 aopGet (AOP (right), offset, FALSE, FALSE),
4214 /* if the right side is in a register or in direct space or
4215 if the left is a pointer register & right is not */
4216 else if (AOP_TYPE (right) == AOP_REG ||
4217 AOP_TYPE (right) == AOP_DIR ||
4218 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4219 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4223 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4224 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4225 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4226 emitcode ("jnz", "%05d$", lbl->key + 100);
4228 emitcode ("cjne", "a,%s,%05d$",
4229 aopGet (AOP (right), offset, FALSE, TRUE),
4236 /* right is a pointer reg need both a & b */
4239 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4240 if (strcmp (l, "b"))
4241 emitcode ("mov", "b,%s", l);
4242 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4243 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4249 /*-----------------------------------------------------------------*/
4250 /* gencjne - compare and jump if not equal */
4251 /*-----------------------------------------------------------------*/
4253 gencjne (operand * left, operand * right, symbol * lbl)
4255 symbol *tlbl = newiTempLabel (NULL);
4257 gencjneshort (left, right, lbl);
4259 emitcode ("mov", "a,%s", one);
4260 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4261 emitcode ("", "%05d$:", lbl->key + 100);
4262 emitcode ("clr", "a");
4263 emitcode ("", "%05d$:", tlbl->key + 100);
4266 /*-----------------------------------------------------------------*/
4267 /* genCmpEq - generates code for equal to */
4268 /*-----------------------------------------------------------------*/
4270 genCmpEq (iCode * ic, iCode * ifx)
4272 operand *left, *right, *result;
4274 D(emitcode ("; genCmpEq",""));
4276 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4277 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4278 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4280 /* if literal, literal on the right or
4281 if the right is in a pointer register and left
4283 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4284 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4286 operand *t = IC_RIGHT (ic);
4287 IC_RIGHT (ic) = IC_LEFT (ic);
4291 if (ifx && !AOP_SIZE (result))
4294 /* if they are both bit variables */
4295 if (AOP_TYPE (left) == AOP_CRY &&
4296 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4298 if (AOP_TYPE (right) == AOP_LIT)
4300 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4304 emitcode ("cpl", "c");
4308 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4312 emitcode ("clr", "c");
4314 /* AOP_TYPE(right) == AOP_CRY */
4318 symbol *lbl = newiTempLabel (NULL);
4319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4320 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4321 emitcode ("cpl", "c");
4322 emitcode ("", "%05d$:", (lbl->key + 100));
4324 /* if true label then we jump if condition
4326 tlbl = newiTempLabel (NULL);
4329 emitcode ("jnc", "%05d$", tlbl->key + 100);
4330 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4334 emitcode ("jc", "%05d$", tlbl->key + 100);
4335 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4337 emitcode ("", "%05d$:", tlbl->key + 100);
4341 tlbl = newiTempLabel (NULL);
4342 gencjneshort (left, right, tlbl);
4345 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4346 emitcode ("", "%05d$:", tlbl->key + 100);
4350 symbol *lbl = newiTempLabel (NULL);
4351 emitcode ("sjmp", "%05d$", lbl->key + 100);
4352 emitcode ("", "%05d$:", tlbl->key + 100);
4353 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4354 emitcode ("", "%05d$:", lbl->key + 100);
4357 /* mark the icode as generated */
4362 /* if they are both bit variables */
4363 if (AOP_TYPE (left) == AOP_CRY &&
4364 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4366 if (AOP_TYPE (right) == AOP_LIT)
4368 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4372 emitcode ("cpl", "c");
4376 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4380 emitcode ("clr", "c");
4382 /* AOP_TYPE(right) == AOP_CRY */
4386 symbol *lbl = newiTempLabel (NULL);
4387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4388 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4389 emitcode ("cpl", "c");
4390 emitcode ("", "%05d$:", (lbl->key + 100));
4393 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4400 genIfxJump (ifx, "c");
4403 /* if the result is used in an arithmetic operation
4404 then put the result in place */
4409 gencjne (left, right, newiTempLabel (NULL));
4410 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4412 aopPut (AOP (result), "a", 0);
4417 genIfxJump (ifx, "a");
4420 /* if the result is used in an arithmetic operation
4421 then put the result in place */
4422 if (AOP_TYPE (result) != AOP_CRY)
4424 /* leave the result in acc */
4428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (result, NULL, ic, TRUE);
4433 /*-----------------------------------------------------------------*/
4434 /* ifxForOp - returns the icode containing the ifx for operand */
4435 /*-----------------------------------------------------------------*/
4437 ifxForOp (operand * op, iCode * ic)
4439 /* if true symbol then needs to be assigned */
4440 if (IS_TRUE_SYMOP (op))
4443 /* if this has register type condition and
4444 the next instruction is ifx with the same operand
4445 and live to of the operand is upto the ifx only then */
4447 ic->next->op == IFX &&
4448 IC_COND (ic->next)->key == op->key &&
4449 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4455 /*-----------------------------------------------------------------*/
4456 /* hasInc - operand is incremented before any other use */
4457 /*-----------------------------------------------------------------*/
4459 hasInc (operand *op, iCode *ic,int osize)
4461 sym_link *type = operandType(op);
4462 sym_link *retype = getSpec (type);
4463 iCode *lic = ic->next;
4466 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4467 if (!IS_SYMOP(op)) return NULL;
4469 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4470 if (IS_AGGREGATE(type->next)) return NULL;
4471 if (osize != (isize = getSize(type->next))) return NULL;
4474 /* if operand of the form op = op + <sizeof *op> */
4475 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4476 isOperandEqual(IC_RESULT(lic),op) &&
4477 isOperandLiteral(IC_RIGHT(lic)) &&
4478 operandLitValue(IC_RIGHT(lic)) == isize) {
4481 /* if the operand used or deffed */
4482 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4485 /* if GOTO or IFX */
4486 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4492 /*-----------------------------------------------------------------*/
4493 /* genAndOp - for && operation */
4494 /*-----------------------------------------------------------------*/
4496 genAndOp (iCode * ic)
4498 operand *left, *right, *result;
4501 D(emitcode ("; genAndOp",""));
4503 /* note here that && operations that are in an
4504 if statement are taken away by backPatchLabels
4505 only those used in arthmetic operations remain */
4506 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4507 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4508 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4510 /* if both are bit variables */
4511 if (AOP_TYPE (left) == AOP_CRY &&
4512 AOP_TYPE (right) == AOP_CRY)
4514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4515 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4520 tlbl = newiTempLabel (NULL);
4522 emitcode ("jz", "%05d$", tlbl->key + 100);
4524 emitcode ("", "%05d$:", tlbl->key + 100);
4528 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 freeAsmop (result, NULL, ic, TRUE);
4534 /*-----------------------------------------------------------------*/
4535 /* genOrOp - for || operation */
4536 /*-----------------------------------------------------------------*/
4538 genOrOp (iCode * ic)
4540 operand *left, *right, *result;
4543 D(emitcode ("; genOrOp",""));
4545 /* note here that || operations that are in an
4546 if statement are taken away by backPatchLabels
4547 only those used in arthmetic operations remain */
4548 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4549 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4550 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4552 /* if both are bit variables */
4553 if (AOP_TYPE (left) == AOP_CRY &&
4554 AOP_TYPE (right) == AOP_CRY)
4556 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4557 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4562 tlbl = newiTempLabel (NULL);
4564 emitcode ("jnz", "%05d$", tlbl->key + 100);
4566 emitcode ("", "%05d$:", tlbl->key + 100);
4570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4572 freeAsmop (result, NULL, ic, TRUE);
4575 /*-----------------------------------------------------------------*/
4576 /* isLiteralBit - test if lit == 2^n */
4577 /*-----------------------------------------------------------------*/
4579 isLiteralBit (unsigned long lit)
4581 unsigned long pw[32] =
4582 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4583 0x100L, 0x200L, 0x400L, 0x800L,
4584 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4585 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4586 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4587 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4588 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4591 for (idx = 0; idx < 32; idx++)
4597 /*-----------------------------------------------------------------*/
4598 /* continueIfTrue - */
4599 /*-----------------------------------------------------------------*/
4601 continueIfTrue (iCode * ic)
4604 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4608 /*-----------------------------------------------------------------*/
4610 /*-----------------------------------------------------------------*/
4612 jumpIfTrue (iCode * ic)
4615 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4619 /*-----------------------------------------------------------------*/
4620 /* jmpTrueOrFalse - */
4621 /*-----------------------------------------------------------------*/
4623 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4625 // ugly but optimized by peephole
4628 symbol *nlbl = newiTempLabel (NULL);
4629 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4630 emitcode ("", "%05d$:", tlbl->key + 100);
4631 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4632 emitcode ("", "%05d$:", nlbl->key + 100);
4636 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4637 emitcode ("", "%05d$:", tlbl->key + 100);
4642 /*-----------------------------------------------------------------*/
4643 /* genAnd - code for and */
4644 /*-----------------------------------------------------------------*/
4646 genAnd (iCode * ic, iCode * ifx)
4648 operand *left, *right, *result;
4649 int size, offset = 0;
4650 unsigned long lit = 0L;
4654 D(emitcode ("; genAnd",""));
4656 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4657 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4658 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4661 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4663 AOP_TYPE (left), AOP_TYPE (right));
4664 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4666 AOP_SIZE (left), AOP_SIZE (right));
4669 /* if left is a literal & right is not then exchange them */
4670 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4671 AOP_NEEDSACC (left))
4673 operand *tmp = right;
4678 /* if result = right then exchange them */
4679 if (sameRegs (AOP (result), AOP (right)))
4681 operand *tmp = right;
4686 /* if right is bit then exchange them */
4687 if (AOP_TYPE (right) == AOP_CRY &&
4688 AOP_TYPE (left) != AOP_CRY)
4690 operand *tmp = right;
4694 if (AOP_TYPE (right) == AOP_LIT)
4695 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4697 size = AOP_SIZE (result);
4700 // result = bit & yy;
4701 if (AOP_TYPE (left) == AOP_CRY)
4703 // c = bit & literal;
4704 if (AOP_TYPE (right) == AOP_LIT)
4708 if (size && sameRegs (AOP (result), AOP (left)))
4711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4716 if (size && (AOP_TYPE (result) == AOP_CRY))
4718 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4721 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4726 emitcode ("clr", "c");
4731 if (AOP_TYPE (right) == AOP_CRY)
4734 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4735 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4740 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4742 emitcode ("rrc", "a");
4743 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4751 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4752 genIfxJump (ifx, "c");
4756 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4757 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4758 if ((AOP_TYPE (right) == AOP_LIT) &&
4759 (AOP_TYPE (result) == AOP_CRY) &&
4760 (AOP_TYPE (left) != AOP_CRY))
4762 int posbit = isLiteralBit (lit);
4767 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4770 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4776 sprintf (buffer, "acc.%d", posbit & 0x07);
4777 genIfxJump (ifx, buffer);
4784 symbol *tlbl = newiTempLabel (NULL);
4785 int sizel = AOP_SIZE (left);
4787 emitcode ("setb", "c");
4790 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4792 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4794 if ((posbit = isLiteralBit (bytelit)) != 0)
4795 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4798 if (bytelit != 0x0FFL)
4799 emitcode ("anl", "a,%s",
4800 aopGet (AOP (right), offset, FALSE, TRUE));
4801 emitcode ("jnz", "%05d$", tlbl->key + 100);
4806 // bit = left & literal
4809 emitcode ("clr", "c");
4810 emitcode ("", "%05d$:", tlbl->key + 100);
4812 // if(left & literal)
4816 jmpTrueOrFalse (ifx, tlbl);
4824 /* if left is same as result */
4825 if (sameRegs (AOP (result), AOP (left)))
4827 for (; size--; offset++)
4829 if (AOP_TYPE (right) == AOP_LIT)
4831 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4833 else if (bytelit == 0)
4834 aopPut (AOP (result), zero, offset);
4835 else if (IS_AOP_PREG (result))
4837 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4838 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4839 aopPut (AOP (result), "a", offset);
4842 emitcode ("anl", "%s,%s",
4843 aopGet (AOP (left), offset, FALSE, TRUE),
4844 aopGet (AOP (right), offset, FALSE, FALSE));
4848 if (AOP_TYPE (left) == AOP_ACC)
4849 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4852 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4853 if (IS_AOP_PREG (result))
4855 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4856 aopPut (AOP (result), "a", offset);
4860 emitcode ("anl", "%s,a",
4861 aopGet (AOP (left), offset, FALSE, TRUE));
4868 // left & result in different registers
4869 if (AOP_TYPE (result) == AOP_CRY)
4872 // if(size), result in bit
4873 // if(!size && ifx), conditional oper: if(left & right)
4874 symbol *tlbl = newiTempLabel (NULL);
4875 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4877 emitcode ("setb", "c");
4880 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4881 emitcode ("anl", "a,%s",
4882 aopGet (AOP (right), offset, FALSE, FALSE));
4884 if (AOP_TYPE(left)==AOP_ACC) {
4885 emitcode("mov", "b,a");
4886 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4887 emitcode("anl", "a,b");
4889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4890 emitcode ("anl", "a,%s",
4891 aopGet (AOP (left), offset, FALSE, FALSE));
4894 emitcode ("jnz", "%05d$", tlbl->key + 100);
4900 emitcode ("", "%05d$:", tlbl->key + 100);
4904 jmpTrueOrFalse (ifx, tlbl);
4908 for (; (size--); offset++)
4911 // result = left & right
4912 if (AOP_TYPE (right) == AOP_LIT)
4914 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4916 aopPut (AOP (result),
4917 aopGet (AOP (left), offset, FALSE, FALSE),
4921 else if (bytelit == 0)
4923 aopPut (AOP (result), zero, offset);
4927 // faster than result <- left, anl result,right
4928 // and better if result is SFR
4929 if (AOP_TYPE (left) == AOP_ACC)
4930 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4934 emitcode ("anl", "a,%s",
4935 aopGet (AOP (left), offset, FALSE, FALSE));
4937 aopPut (AOP (result), "a", offset);
4943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4945 freeAsmop (result, NULL, ic, TRUE);
4948 /*-----------------------------------------------------------------*/
4949 /* genOr - code for or */
4950 /*-----------------------------------------------------------------*/
4952 genOr (iCode * ic, iCode * ifx)
4954 operand *left, *right, *result;
4955 int size, offset = 0;
4956 unsigned long lit = 0L;
4958 D(emitcode ("; genOr",""));
4960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4965 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4967 AOP_TYPE (left), AOP_TYPE (right));
4968 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4970 AOP_SIZE (left), AOP_SIZE (right));
4973 /* if left is a literal & right is not then exchange them */
4974 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4975 AOP_NEEDSACC (left))
4977 operand *tmp = right;
4982 /* if result = right then exchange them */
4983 if (sameRegs (AOP (result), AOP (right)))
4985 operand *tmp = right;
4990 /* if right is bit then exchange them */
4991 if (AOP_TYPE (right) == AOP_CRY &&
4992 AOP_TYPE (left) != AOP_CRY)
4994 operand *tmp = right;
4998 if (AOP_TYPE (right) == AOP_LIT)
4999 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5001 size = AOP_SIZE (result);
5005 if (AOP_TYPE (left) == AOP_CRY)
5007 if (AOP_TYPE (right) == AOP_LIT)
5009 // c = bit | literal;
5012 // lit != 0 => result = 1
5013 if (AOP_TYPE (result) == AOP_CRY)
5016 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5018 continueIfTrue (ifx);
5021 emitcode ("setb", "c");
5025 // lit == 0 => result = left
5026 if (size && sameRegs (AOP (result), AOP (left)))
5028 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5033 if (AOP_TYPE (right) == AOP_CRY)
5036 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5037 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5042 symbol *tlbl = newiTempLabel (NULL);
5043 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5044 emitcode ("setb", "c");
5045 emitcode ("jb", "%s,%05d$",
5046 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5048 emitcode ("jnz", "%05d$", tlbl->key + 100);
5049 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5051 jmpTrueOrFalse (ifx, tlbl);
5057 emitcode ("", "%05d$:", tlbl->key + 100);
5066 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5067 genIfxJump (ifx, "c");
5071 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5072 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5073 if ((AOP_TYPE (right) == AOP_LIT) &&
5074 (AOP_TYPE (result) == AOP_CRY) &&
5075 (AOP_TYPE (left) != AOP_CRY))
5081 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5083 continueIfTrue (ifx);
5088 // lit = 0, result = boolean(left)
5090 emitcode ("setb", "c");
5094 symbol *tlbl = newiTempLabel (NULL);
5095 emitcode ("jnz", "%05d$", tlbl->key + 100);
5097 emitcode ("", "%05d$:", tlbl->key + 100);
5101 genIfxJump (ifx, "a");
5109 /* if left is same as result */
5110 if (sameRegs (AOP (result), AOP (left)))
5112 for (; size--; offset++)
5114 if (AOP_TYPE (right) == AOP_LIT)
5116 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5118 else if (IS_AOP_PREG (left))
5120 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5121 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5122 aopPut (AOP (result), "a", offset);
5125 emitcode ("orl", "%s,%s",
5126 aopGet (AOP (left), offset, FALSE, TRUE),
5127 aopGet (AOP (right), offset, FALSE, FALSE));
5131 if (AOP_TYPE (left) == AOP_ACC)
5132 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5135 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5136 if (IS_AOP_PREG (left))
5138 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5139 aopPut (AOP (result), "a", offset);
5142 emitcode ("orl", "%s,a",
5143 aopGet (AOP (left), offset, FALSE, TRUE));
5150 // left & result in different registers
5151 if (AOP_TYPE (result) == AOP_CRY)
5154 // if(size), result in bit
5155 // if(!size && ifx), conditional oper: if(left | right)
5156 symbol *tlbl = newiTempLabel (NULL);
5157 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5159 emitcode ("setb", "c");
5162 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5163 emitcode ("orl", "a,%s",
5164 aopGet (AOP (right), offset, FALSE, FALSE));
5166 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5167 emitcode ("orl", "a,%s",
5168 aopGet (AOP (left), offset, FALSE, FALSE));
5170 emitcode ("jnz", "%05d$", tlbl->key + 100);
5176 emitcode ("", "%05d$:", tlbl->key + 100);
5180 jmpTrueOrFalse (ifx, tlbl);
5183 for (; (size--); offset++)
5186 // result = left & right
5187 if (AOP_TYPE (right) == AOP_LIT)
5189 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5191 aopPut (AOP (result),
5192 aopGet (AOP (left), offset, FALSE, FALSE),
5197 // faster than result <- left, anl result,right
5198 // and better if result is SFR
5199 if (AOP_TYPE (left) == AOP_ACC)
5200 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5203 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5204 emitcode ("orl", "a,%s",
5205 aopGet (AOP (left), offset, FALSE, FALSE));
5207 aopPut (AOP (result), "a", offset);
5212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 freeAsmop (result, NULL, ic, TRUE);
5217 /*-----------------------------------------------------------------*/
5218 /* genXor - code for xclusive or */
5219 /*-----------------------------------------------------------------*/
5221 genXor (iCode * ic, iCode * ifx)
5223 operand *left, *right, *result;
5224 int size, offset = 0;
5225 unsigned long lit = 0L;
5227 D(emitcode ("; genXor",""));
5229 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5230 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5231 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5234 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5236 AOP_TYPE (left), AOP_TYPE (right));
5237 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5239 AOP_SIZE (left), AOP_SIZE (right));
5242 /* if left is a literal & right is not ||
5243 if left needs acc & right does not */
5244 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5245 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5247 operand *tmp = right;
5252 /* if result = right then exchange them */
5253 if (sameRegs (AOP (result), AOP (right)))
5255 operand *tmp = right;
5260 /* if right is bit then exchange them */
5261 if (AOP_TYPE (right) == AOP_CRY &&
5262 AOP_TYPE (left) != AOP_CRY)
5264 operand *tmp = right;
5268 if (AOP_TYPE (right) == AOP_LIT)
5269 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5271 size = AOP_SIZE (result);
5275 if (AOP_TYPE (left) == AOP_CRY)
5277 if (AOP_TYPE (right) == AOP_LIT)
5279 // c = bit & literal;
5282 // lit>>1 != 0 => result = 1
5283 if (AOP_TYPE (result) == AOP_CRY)
5286 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5288 continueIfTrue (ifx);
5291 emitcode ("setb", "c");
5298 // lit == 0, result = left
5299 if (size && sameRegs (AOP (result), AOP (left)))
5301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5305 // lit == 1, result = not(left)
5306 if (size && sameRegs (AOP (result), AOP (left)))
5308 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5313 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5314 emitcode ("cpl", "c");
5323 symbol *tlbl = newiTempLabel (NULL);
5324 if (AOP_TYPE (right) == AOP_CRY)
5327 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5331 int sizer = AOP_SIZE (right);
5333 // if val>>1 != 0, result = 1
5334 emitcode ("setb", "c");
5337 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5339 // test the msb of the lsb
5340 emitcode ("anl", "a,#0xfe");
5341 emitcode ("jnz", "%05d$", tlbl->key + 100);
5345 emitcode ("rrc", "a");
5347 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5348 emitcode ("cpl", "c");
5349 emitcode ("", "%05d$:", (tlbl->key + 100));
5356 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5357 genIfxJump (ifx, "c");
5361 if (sameRegs (AOP (result), AOP (left)))
5363 /* if left is same as result */
5364 for (; size--; offset++)
5366 if (AOP_TYPE (right) == AOP_LIT)
5368 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5370 else if (IS_AOP_PREG (left))
5372 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5373 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5374 aopPut (AOP (result), "a", offset);
5377 emitcode ("xrl", "%s,%s",
5378 aopGet (AOP (left), offset, FALSE, TRUE),
5379 aopGet (AOP (right), offset, FALSE, FALSE));
5383 if (AOP_TYPE (left) == AOP_ACC)
5384 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5387 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5388 if (IS_AOP_PREG (left))
5390 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5391 aopPut (AOP (result), "a", offset);
5394 emitcode ("xrl", "%s,a",
5395 aopGet (AOP (left), offset, FALSE, TRUE));
5402 // left & result in different registers
5403 if (AOP_TYPE (result) == AOP_CRY)
5406 // if(size), result in bit
5407 // if(!size && ifx), conditional oper: if(left ^ right)
5408 symbol *tlbl = newiTempLabel (NULL);
5409 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5411 emitcode ("setb", "c");
5414 if ((AOP_TYPE (right) == AOP_LIT) &&
5415 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5417 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5421 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5422 emitcode ("xrl", "a,%s",
5423 aopGet (AOP (right), offset, FALSE, FALSE));
5425 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5426 emitcode ("xrl", "a,%s",
5427 aopGet (AOP (left), offset, FALSE, FALSE));
5430 emitcode ("jnz", "%05d$", tlbl->key + 100);
5436 emitcode ("", "%05d$:", tlbl->key + 100);
5440 jmpTrueOrFalse (ifx, tlbl);
5443 for (; (size--); offset++)
5446 // result = left & right
5447 if (AOP_TYPE (right) == AOP_LIT)
5449 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5451 aopPut (AOP (result),
5452 aopGet (AOP (left), offset, FALSE, FALSE),
5457 // faster than result <- left, anl result,right
5458 // and better if result is SFR
5459 if (AOP_TYPE (left) == AOP_ACC)
5460 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5463 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5464 emitcode ("xrl", "a,%s",
5465 aopGet (AOP (left), offset, FALSE, TRUE));
5467 aopPut (AOP (result), "a", offset);
5472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5474 freeAsmop (result, NULL, ic, TRUE);
5477 /*-----------------------------------------------------------------*/
5478 /* genInline - write the inline code out */
5479 /*-----------------------------------------------------------------*/
5481 genInline (iCode * ic)
5483 char *buffer, *bp, *bp1;
5485 D(emitcode ("; genInline",""));
5487 _G.inLine += (!options.asmpeep);
5489 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5490 strcpy (buffer, IC_INLINE (ic));
5492 /* emit each line as a code */
5517 /* emitcode("",buffer); */
5518 _G.inLine -= (!options.asmpeep);
5521 /*-----------------------------------------------------------------*/
5522 /* genRRC - rotate right with carry */
5523 /*-----------------------------------------------------------------*/
5527 operand *left, *result;
5528 int size, offset = 0;
5531 D(emitcode ("; genRRC",""));
5533 /* rotate right with carry */
5534 left = IC_LEFT (ic);
5535 result = IC_RESULT (ic);
5536 aopOp (left, ic, FALSE);
5537 aopOp (result, ic, FALSE);
5539 /* move it to the result */
5540 size = AOP_SIZE (result);
5542 if (size == 1) { /* special case for 1 byte */
5543 l = aopGet (AOP (left), offset, FALSE, FALSE);
5545 emitcode ("rr", "a");
5551 l = aopGet (AOP (left), offset, FALSE, FALSE);
5553 emitcode ("rrc", "a");
5554 if (AOP_SIZE (result) > 1)
5555 aopPut (AOP (result), "a", offset--);
5557 /* now we need to put the carry into the
5558 highest order byte of the result */
5559 if (AOP_SIZE (result) > 1)
5561 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5564 emitcode ("mov", "acc.7,c");
5566 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5567 freeAsmop (left, NULL, ic, TRUE);
5568 freeAsmop (result, NULL, ic, TRUE);
5571 /*-----------------------------------------------------------------*/
5572 /* genRLC - generate code for rotate left with carry */
5573 /*-----------------------------------------------------------------*/
5577 operand *left, *result;
5578 int size, offset = 0;
5581 D(emitcode ("; genRLC",""));
5583 /* rotate right with carry */
5584 left = IC_LEFT (ic);
5585 result = IC_RESULT (ic);
5586 aopOp (left, ic, FALSE);
5587 aopOp (result, ic, FALSE);
5589 /* move it to the result */
5590 size = AOP_SIZE (result);
5594 l = aopGet (AOP (left), offset, FALSE, FALSE);
5596 if (size == 0) { /* special case for 1 byte */
5600 emitcode ("add", "a,acc");
5601 if (AOP_SIZE (result) > 1)
5602 aopPut (AOP (result), "a", offset++);
5605 l = aopGet (AOP (left), offset, FALSE, FALSE);
5607 emitcode ("rlc", "a");
5608 if (AOP_SIZE (result) > 1)
5609 aopPut (AOP (result), "a", offset++);
5612 /* now we need to put the carry into the
5613 highest order byte of the result */
5614 if (AOP_SIZE (result) > 1)
5616 l = aopGet (AOP (result), 0, FALSE, FALSE);
5619 emitcode ("mov", "acc.0,c");
5621 aopPut (AOP (result), "a", 0);
5622 freeAsmop (left, NULL, ic, TRUE);
5623 freeAsmop (result, NULL, ic, TRUE);
5626 /*-----------------------------------------------------------------*/
5627 /* genGetHbit - generates code get highest order bit */
5628 /*-----------------------------------------------------------------*/
5630 genGetHbit (iCode * ic)
5632 operand *left, *result;
5634 D(emitcode ("; genGetHbit",""));
5636 left = IC_LEFT (ic);
5637 result = IC_RESULT (ic);
5638 aopOp (left, ic, FALSE);
5639 aopOp (result, ic, FALSE);
5641 /* get the highest order byte into a */
5642 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5643 if (AOP_TYPE (result) == AOP_CRY)
5645 emitcode ("rlc", "a");
5650 emitcode ("rl", "a");
5651 emitcode ("anl", "a,#0x01");
5656 freeAsmop (left, NULL, ic, TRUE);
5657 freeAsmop (result, NULL, ic, TRUE);
5660 /*-----------------------------------------------------------------*/
5661 /* AccRol - rotate left accumulator by known count */
5662 /*-----------------------------------------------------------------*/
5664 AccRol (int shCount)
5666 shCount &= 0x0007; // shCount : 0..7
5673 emitcode ("rl", "a");
5676 emitcode ("rl", "a");
5677 emitcode ("rl", "a");
5680 emitcode ("swap", "a");
5681 emitcode ("rr", "a");
5684 emitcode ("swap", "a");
5687 emitcode ("swap", "a");
5688 emitcode ("rl", "a");
5691 emitcode ("rr", "a");
5692 emitcode ("rr", "a");
5695 emitcode ("rr", "a");
5700 /*-----------------------------------------------------------------*/
5701 /* AccLsh - left shift accumulator by known count */
5702 /*-----------------------------------------------------------------*/
5704 AccLsh (int shCount)
5709 emitcode ("add", "a,acc");
5710 else if (shCount == 2)
5712 emitcode ("add", "a,acc");
5713 emitcode ("add", "a,acc");
5717 /* rotate left accumulator */
5719 /* and kill the lower order bits */
5720 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5725 /*-----------------------------------------------------------------*/
5726 /* AccRsh - right shift accumulator by known count */
5727 /*-----------------------------------------------------------------*/
5729 AccRsh (int shCount)
5736 emitcode ("rrc", "a");
5740 /* rotate right accumulator */
5741 AccRol (8 - shCount);
5742 /* and kill the higher order bits */
5743 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5748 /*-----------------------------------------------------------------*/
5749 /* AccSRsh - signed right shift accumulator by known count */
5750 /*-----------------------------------------------------------------*/
5752 AccSRsh (int shCount)
5759 emitcode ("mov", "c,acc.7");
5760 emitcode ("rrc", "a");
5762 else if (shCount == 2)
5764 emitcode ("mov", "c,acc.7");
5765 emitcode ("rrc", "a");
5766 emitcode ("mov", "c,acc.7");
5767 emitcode ("rrc", "a");
5771 tlbl = newiTempLabel (NULL);
5772 /* rotate right accumulator */
5773 AccRol (8 - shCount);
5774 /* and kill the higher order bits */
5775 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5776 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5777 emitcode ("orl", "a,#0x%02x",
5778 (unsigned char) ~SRMask[shCount]);
5779 emitcode ("", "%05d$:", tlbl->key + 100);
5784 /*-----------------------------------------------------------------*/
5785 /* shiftR1Left2Result - shift right one byte from left to result */
5786 /*-----------------------------------------------------------------*/
5788 shiftR1Left2Result (operand * left, int offl,
5789 operand * result, int offr,
5790 int shCount, int sign)
5792 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5793 /* shift right accumulator */
5798 aopPut (AOP (result), "a", offr);
5801 /*-----------------------------------------------------------------*/
5802 /* shiftL1Left2Result - shift left one byte from left to result */
5803 /*-----------------------------------------------------------------*/
5805 shiftL1Left2Result (operand * left, int offl,
5806 operand * result, int offr, int shCount)
5809 l = aopGet (AOP (left), offl, FALSE, FALSE);
5811 /* shift left accumulator */
5813 aopPut (AOP (result), "a", offr);
5816 /*-----------------------------------------------------------------*/
5817 /* movLeft2Result - move byte from left to result */
5818 /*-----------------------------------------------------------------*/
5820 movLeft2Result (operand * left, int offl,
5821 operand * result, int offr, int sign)
5824 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5826 l = aopGet (AOP (left), offl, FALSE, FALSE);
5828 if (*l == '@' && (IS_AOP_PREG (result)))
5830 emitcode ("mov", "a,%s", l);
5831 aopPut (AOP (result), "a", offr);
5836 aopPut (AOP (result), l, offr);
5839 /* MSB sign in acc.7 ! */
5840 if (getDataSize (left) == offl + 1)
5842 emitcode ("mov", "a,%s", l);
5843 aopPut (AOP (result), "a", offr);
5850 /*-----------------------------------------------------------------*/
5851 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5852 /*-----------------------------------------------------------------*/
5856 emitcode ("rrc", "a");
5857 emitcode ("xch", "a,%s", x);
5858 emitcode ("rrc", "a");
5859 emitcode ("xch", "a,%s", x);
5862 /*-----------------------------------------------------------------*/
5863 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5864 /*-----------------------------------------------------------------*/
5868 emitcode ("xch", "a,%s", x);
5869 emitcode ("rlc", "a");
5870 emitcode ("xch", "a,%s", x);
5871 emitcode ("rlc", "a");
5874 /*-----------------------------------------------------------------*/
5875 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5876 /*-----------------------------------------------------------------*/
5880 emitcode ("xch", "a,%s", x);
5881 emitcode ("add", "a,acc");
5882 emitcode ("xch", "a,%s", x);
5883 emitcode ("rlc", "a");
5886 /*-----------------------------------------------------------------*/
5887 /* AccAXLsh - left shift a:x by known count (0..7) */
5888 /*-----------------------------------------------------------------*/
5890 AccAXLsh (char *x, int shCount)
5905 case 5: // AAAAABBB:CCCCCDDD
5907 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5909 emitcode ("anl", "a,#0x%02x",
5910 SLMask[shCount]); // BBB00000:CCCCCDDD
5912 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5914 AccRol (shCount); // DDDCCCCC:BBB00000
5916 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5918 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5920 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5922 emitcode ("anl", "a,#0x%02x",
5923 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5925 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5927 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5930 case 6: // AAAAAABB:CCCCCCDD
5931 emitcode ("anl", "a,#0x%02x",
5932 SRMask[shCount]); // 000000BB:CCCCCCDD
5933 emitcode ("mov", "c,acc.0"); // c = B
5934 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5936 AccAXRrl1 (x); // BCCCCCCD:D000000B
5937 AccAXRrl1 (x); // BBCCCCCC:DD000000
5939 emitcode("rrc","a");
5940 emitcode("xch","a,%s", x);
5941 emitcode("rrc","a");
5942 emitcode("mov","c,acc.0"); //<< get correct bit
5943 emitcode("xch","a,%s", x);
5945 emitcode("rrc","a");
5946 emitcode("xch","a,%s", x);
5947 emitcode("rrc","a");
5948 emitcode("xch","a,%s", x);
5951 case 7: // a:x <<= 7
5953 emitcode ("anl", "a,#0x%02x",
5954 SRMask[shCount]); // 0000000B:CCCCCCCD
5956 emitcode ("mov", "c,acc.0"); // c = B
5958 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5960 AccAXRrl1 (x); // BCCCCCCC:D0000000
5968 /*-----------------------------------------------------------------*/
5969 /* AccAXRsh - right shift a:x known count (0..7) */
5970 /*-----------------------------------------------------------------*/
5972 AccAXRsh (char *x, int shCount)
5980 AccAXRrl1 (x); // 0->a:x
5985 AccAXRrl1 (x); // 0->a:x
5988 AccAXRrl1 (x); // 0->a:x
5993 case 5: // AAAAABBB:CCCCCDDD = a:x
5995 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5997 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5999 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6001 emitcode ("anl", "a,#0x%02x",
6002 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6004 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6006 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6008 emitcode ("anl", "a,#0x%02x",
6009 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6011 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6013 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6015 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6018 case 6: // AABBBBBB:CCDDDDDD
6020 emitcode ("mov", "c,acc.7");
6021 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6023 emitcode ("mov", "c,acc.7");
6024 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6026 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6028 emitcode ("anl", "a,#0x%02x",
6029 SRMask[shCount]); // 000000AA:BBBBBBCC
6032 case 7: // ABBBBBBB:CDDDDDDD
6034 emitcode ("mov", "c,acc.7"); // c = A
6036 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6038 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6040 emitcode ("anl", "a,#0x%02x",
6041 SRMask[shCount]); // 0000000A:BBBBBBBC
6049 /*-----------------------------------------------------------------*/
6050 /* AccAXRshS - right shift signed a:x known count (0..7) */
6051 /*-----------------------------------------------------------------*/
6053 AccAXRshS (char *x, int shCount)
6061 emitcode ("mov", "c,acc.7");
6062 AccAXRrl1 (x); // s->a:x
6066 emitcode ("mov", "c,acc.7");
6067 AccAXRrl1 (x); // s->a:x
6069 emitcode ("mov", "c,acc.7");
6070 AccAXRrl1 (x); // s->a:x
6075 case 5: // AAAAABBB:CCCCCDDD = a:x
6077 tlbl = newiTempLabel (NULL);
6078 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6080 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6082 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6084 emitcode ("anl", "a,#0x%02x",
6085 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6087 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6089 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6091 emitcode ("anl", "a,#0x%02x",
6092 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6094 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6096 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6098 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6100 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6101 emitcode ("orl", "a,#0x%02x",
6102 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6104 emitcode ("", "%05d$:", tlbl->key + 100);
6105 break; // SSSSAAAA:BBBCCCCC
6107 case 6: // AABBBBBB:CCDDDDDD
6109 tlbl = newiTempLabel (NULL);
6110 emitcode ("mov", "c,acc.7");
6111 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6113 emitcode ("mov", "c,acc.7");
6114 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6116 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6118 emitcode ("anl", "a,#0x%02x",
6119 SRMask[shCount]); // 000000AA:BBBBBBCC
6121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6122 emitcode ("orl", "a,#0x%02x",
6123 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6125 emitcode ("", "%05d$:", tlbl->key + 100);
6127 case 7: // ABBBBBBB:CDDDDDDD
6129 tlbl = newiTempLabel (NULL);
6130 emitcode ("mov", "c,acc.7"); // c = A
6132 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6134 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6136 emitcode ("anl", "a,#0x%02x",
6137 SRMask[shCount]); // 0000000A:BBBBBBBC
6139 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6140 emitcode ("orl", "a,#0x%02x",
6141 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6143 emitcode ("", "%05d$:", tlbl->key + 100);
6150 /*-----------------------------------------------------------------*/
6151 /* shiftL2Left2Result - shift left two bytes from left to result */
6152 /*-----------------------------------------------------------------*/
6154 shiftL2Left2Result (operand * left, int offl,
6155 operand * result, int offr, int shCount)
6157 if (sameRegs (AOP (result), AOP (left)) &&
6158 ((offl + MSB16) == offr))
6160 /* don't crash result[offr] */
6161 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6162 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6166 movLeft2Result (left, offl, result, offr, 0);
6167 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6169 /* ax << shCount (x = lsb(result)) */
6170 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6171 aopPut (AOP (result), "a", offr + MSB16);
6175 /*-----------------------------------------------------------------*/
6176 /* shiftR2Left2Result - shift right two bytes from left to result */
6177 /*-----------------------------------------------------------------*/
6179 shiftR2Left2Result (operand * left, int offl,
6180 operand * result, int offr,
6181 int shCount, int sign)
6183 if (sameRegs (AOP (result), AOP (left)) &&
6184 ((offl + MSB16) == offr))
6186 /* don't crash result[offr] */
6187 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6188 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6192 movLeft2Result (left, offl, result, offr, 0);
6193 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6195 /* a:x >> shCount (x = lsb(result)) */
6197 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6199 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6200 if (getDataSize (result) > 1)
6201 aopPut (AOP (result), "a", offr + MSB16);
6204 /*-----------------------------------------------------------------*/
6205 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6206 /*-----------------------------------------------------------------*/
6208 shiftLLeftOrResult (operand * left, int offl,
6209 operand * result, int offr, int shCount)
6211 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6212 /* shift left accumulator */
6214 /* or with result */
6215 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6216 /* back to result */
6217 aopPut (AOP (result), "a", offr);
6220 /*-----------------------------------------------------------------*/
6221 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6222 /*-----------------------------------------------------------------*/
6224 shiftRLeftOrResult (operand * left, int offl,
6225 operand * result, int offr, int shCount)
6227 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6228 /* shift right accumulator */
6230 /* or with result */
6231 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6232 /* back to result */
6233 aopPut (AOP (result), "a", offr);
6236 /*-----------------------------------------------------------------*/
6237 /* genlshOne - left shift a one byte quantity by known count */
6238 /*-----------------------------------------------------------------*/
6240 genlshOne (operand * result, operand * left, int shCount)
6242 D(emitcode ("; genlshOne",""));
6244 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6247 /*-----------------------------------------------------------------*/
6248 /* genlshTwo - left shift two bytes by known amount != 0 */
6249 /*-----------------------------------------------------------------*/
6251 genlshTwo (operand * result, operand * left, int shCount)
6255 D(emitcode ("; genlshTwo",""));
6257 size = getDataSize (result);
6259 /* if shCount >= 8 */
6267 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6269 movLeft2Result (left, LSB, result, MSB16, 0);
6271 aopPut (AOP (result), zero, LSB);
6274 /* 1 <= shCount <= 7 */
6278 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6280 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6284 /*-----------------------------------------------------------------*/
6285 /* shiftLLong - shift left one long from left to result */
6286 /* offl = LSB or MSB16 */
6287 /*-----------------------------------------------------------------*/
6289 shiftLLong (operand * left, operand * result, int offr)
6292 int size = AOP_SIZE (result);
6294 if (size >= LSB + offr)
6296 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6298 emitcode ("add", "a,acc");
6299 if (sameRegs (AOP (left), AOP (result)) &&
6300 size >= MSB16 + offr && offr != LSB)
6301 emitcode ("xch", "a,%s",
6302 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6304 aopPut (AOP (result), "a", LSB + offr);
6307 if (size >= MSB16 + offr)
6309 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6311 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6314 emitcode ("rlc", "a");
6315 if (sameRegs (AOP (left), AOP (result)) &&
6316 size >= MSB24 + offr && offr != LSB)
6317 emitcode ("xch", "a,%s",
6318 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6320 aopPut (AOP (result), "a", MSB16 + offr);
6323 if (size >= MSB24 + offr)
6325 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6327 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6330 emitcode ("rlc", "a");
6331 if (sameRegs (AOP (left), AOP (result)) &&
6332 size >= MSB32 + offr && offr != LSB)
6333 emitcode ("xch", "a,%s",
6334 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6336 aopPut (AOP (result), "a", MSB24 + offr);
6339 if (size > MSB32 + offr)
6341 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6343 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6346 emitcode ("rlc", "a");
6347 aopPut (AOP (result), "a", MSB32 + offr);
6350 aopPut (AOP (result), zero, LSB);
6353 /*-----------------------------------------------------------------*/
6354 /* genlshFour - shift four byte by a known amount != 0 */
6355 /*-----------------------------------------------------------------*/
6357 genlshFour (operand * result, operand * left, int shCount)
6361 D(emitcode ("; genlshFour",""));
6363 size = AOP_SIZE (result);
6365 /* if shifting more that 3 bytes */
6370 /* lowest order of left goes to the highest
6371 order of the destination */
6372 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6374 movLeft2Result (left, LSB, result, MSB32, 0);
6375 aopPut (AOP (result), zero, LSB);
6376 aopPut (AOP (result), zero, MSB16);
6377 aopPut (AOP (result), zero, MSB24);
6381 /* more than two bytes */
6382 else if (shCount >= 16)
6384 /* lower order two bytes goes to higher order two bytes */
6386 /* if some more remaining */
6388 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6391 movLeft2Result (left, MSB16, result, MSB32, 0);
6392 movLeft2Result (left, LSB, result, MSB24, 0);
6394 aopPut (AOP (result), zero, MSB16);
6395 aopPut (AOP (result), zero, LSB);
6399 /* if more than 1 byte */
6400 else if (shCount >= 8)
6402 /* lower order three bytes goes to higher order three bytes */
6407 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6409 movLeft2Result (left, LSB, result, MSB16, 0);
6415 movLeft2Result (left, MSB24, result, MSB32, 0);
6416 movLeft2Result (left, MSB16, result, MSB24, 0);
6417 movLeft2Result (left, LSB, result, MSB16, 0);
6418 aopPut (AOP (result), zero, LSB);
6420 else if (shCount == 1)
6421 shiftLLong (left, result, MSB16);
6424 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6425 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6426 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6427 aopPut (AOP (result), zero, LSB);
6432 /* 1 <= shCount <= 7 */
6433 else if (shCount <= 2)
6435 shiftLLong (left, result, LSB);
6437 shiftLLong (result, result, LSB);
6439 /* 3 <= shCount <= 7, optimize */
6442 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6443 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6444 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6448 /*-----------------------------------------------------------------*/
6449 /* genLeftShiftLiteral - left shifting by known count */
6450 /*-----------------------------------------------------------------*/
6452 genLeftShiftLiteral (operand * left,
6457 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6460 D(emitcode ("; genLeftShiftLiteral",""));
6462 freeAsmop (right, NULL, ic, TRUE);
6464 aopOp (left, ic, FALSE);
6465 aopOp (result, ic, FALSE);
6467 size = getSize (operandType (result));
6470 emitcode ("; shift left ", "result %d, left %d", size,
6474 /* I suppose that the left size >= result size */
6479 movLeft2Result (left, size, result, size, 0);
6483 else if (shCount >= (size * 8))
6485 aopPut (AOP (result), zero, size);
6491 genlshOne (result, left, shCount);
6495 genlshTwo (result, left, shCount);
6499 genlshFour (result, left, shCount);
6502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6503 "*** ack! mystery literal shift!\n");
6507 freeAsmop (left, NULL, ic, TRUE);
6508 freeAsmop (result, NULL, ic, TRUE);
6511 /*-----------------------------------------------------------------*/
6512 /* genLeftShift - generates code for left shifting */
6513 /*-----------------------------------------------------------------*/
6515 genLeftShift (iCode * ic)
6517 operand *left, *right, *result;
6520 symbol *tlbl, *tlbl1;
6522 D(emitcode ("; genLeftShift",""));
6524 right = IC_RIGHT (ic);
6525 left = IC_LEFT (ic);
6526 result = IC_RESULT (ic);
6528 aopOp (right, ic, FALSE);
6530 /* if the shift count is known then do it
6531 as efficiently as possible */
6532 if (AOP_TYPE (right) == AOP_LIT)
6534 genLeftShiftLiteral (left, right, result, ic);
6538 /* shift count is unknown then we have to form
6539 a loop get the loop count in B : Note: we take
6540 only the lower order byte since shifting
6541 more that 32 bits make no sense anyway, ( the
6542 largest size of an object can be only 32 bits ) */
6544 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6545 emitcode ("inc", "b");
6546 freeAsmop (right, NULL, ic, TRUE);
6547 aopOp (left, ic, FALSE);
6548 aopOp (result, ic, FALSE);
6550 /* now move the left to the result if they are not the
6552 if (!sameRegs (AOP (left), AOP (result)) &&
6553 AOP_SIZE (result) > 1)
6556 size = AOP_SIZE (result);
6560 l = aopGet (AOP (left), offset, FALSE, TRUE);
6561 if (*l == '@' && (IS_AOP_PREG (result)))
6564 emitcode ("mov", "a,%s", l);
6565 aopPut (AOP (result), "a", offset);
6568 aopPut (AOP (result), l, offset);
6573 tlbl = newiTempLabel (NULL);
6574 size = AOP_SIZE (result);
6576 tlbl1 = newiTempLabel (NULL);
6578 /* if it is only one byte then */
6581 symbol *tlbl1 = newiTempLabel (NULL);
6583 l = aopGet (AOP (left), 0, FALSE, FALSE);
6585 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6586 emitcode ("", "%05d$:", tlbl->key + 100);
6587 emitcode ("add", "a,acc");
6588 emitcode ("", "%05d$:", tlbl1->key + 100);
6589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6590 aopPut (AOP (result), "a", 0);
6594 reAdjustPreg (AOP (result));
6596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6597 emitcode ("", "%05d$:", tlbl->key + 100);
6598 l = aopGet (AOP (result), offset, FALSE, FALSE);
6600 emitcode ("add", "a,acc");
6601 aopPut (AOP (result), "a", offset++);
6604 l = aopGet (AOP (result), offset, FALSE, FALSE);
6606 emitcode ("rlc", "a");
6607 aopPut (AOP (result), "a", offset++);
6609 reAdjustPreg (AOP (result));
6611 emitcode ("", "%05d$:", tlbl1->key + 100);
6612 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6614 freeAsmop (left, NULL, ic, TRUE);
6615 freeAsmop (result, NULL, ic, TRUE);
6618 /*-----------------------------------------------------------------*/
6619 /* genrshOne - right shift a one byte quantity by known count */
6620 /*-----------------------------------------------------------------*/
6622 genrshOne (operand * result, operand * left,
6623 int shCount, int sign)
6625 D(emitcode ("; genrshOne",""));
6627 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6630 /*-----------------------------------------------------------------*/
6631 /* genrshTwo - right shift two bytes by known amount != 0 */
6632 /*-----------------------------------------------------------------*/
6634 genrshTwo (operand * result, operand * left,
6635 int shCount, int sign)
6637 D(emitcode ("; genrshTwo",""));
6639 /* if shCount >= 8 */
6644 shiftR1Left2Result (left, MSB16, result, LSB,
6647 movLeft2Result (left, MSB16, result, LSB, sign);
6648 addSign (result, MSB16, sign);
6651 /* 1 <= shCount <= 7 */
6653 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6656 /*-----------------------------------------------------------------*/
6657 /* shiftRLong - shift right one long from left to result */
6658 /* offl = LSB or MSB16 */
6659 /*-----------------------------------------------------------------*/
6661 shiftRLong (operand * left, int offl,
6662 operand * result, int sign)
6664 int isSameRegs=sameRegs(AOP(left),AOP(result));
6666 if (isSameRegs && offl>1) {
6667 // we are in big trouble, but this shouldn't happen
6668 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6671 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6676 emitcode ("rlc", "a");
6677 emitcode ("subb", "a,acc");
6679 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6681 aopPut (AOP (result), "a", MSB32);
6682 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6685 aopPut (AOP(result), zero, MSB32);
6690 emitcode ("clr", "c");
6692 emitcode ("mov", "c,acc.7");
6695 emitcode ("rrc", "a");
6697 if (isSameRegs && offl==MSB16) {
6698 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6700 aopPut (AOP (result), "a", MSB32-offl);
6701 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6704 emitcode ("rrc", "a");
6705 if (isSameRegs && offl==1) {
6706 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6708 aopPut (AOP (result), "a", MSB24-offl);
6709 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6711 emitcode ("rrc", "a");
6712 aopPut (AOP (result), "a", MSB16 - offl);
6716 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6717 emitcode ("rrc", "a");
6718 aopPut (AOP (result), "a", LSB);
6722 /*-----------------------------------------------------------------*/
6723 /* genrshFour - shift four byte by a known amount != 0 */
6724 /*-----------------------------------------------------------------*/
6726 genrshFour (operand * result, operand * left,
6727 int shCount, int sign)
6729 D(emitcode ("; genrshFour",""));
6731 /* if shifting more that 3 bytes */
6736 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6738 movLeft2Result (left, MSB32, result, LSB, sign);
6739 addSign (result, MSB16, sign);
6741 else if (shCount >= 16)
6745 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6748 movLeft2Result (left, MSB24, result, LSB, 0);
6749 movLeft2Result (left, MSB32, result, MSB16, sign);
6751 addSign (result, MSB24, sign);
6753 else if (shCount >= 8)
6757 shiftRLong (left, MSB16, result, sign);
6758 else if (shCount == 0)
6760 movLeft2Result (left, MSB16, result, LSB, 0);
6761 movLeft2Result (left, MSB24, result, MSB16, 0);
6762 movLeft2Result (left, MSB32, result, MSB24, sign);
6763 addSign (result, MSB32, sign);
6767 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6768 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6769 /* the last shift is signed */
6770 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6771 addSign (result, MSB32, sign);
6775 { /* 1 <= shCount <= 7 */
6778 shiftRLong (left, LSB, result, sign);
6780 shiftRLong (result, LSB, result, sign);
6784 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6785 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6786 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6791 /*-----------------------------------------------------------------*/
6792 /* genRightShiftLiteral - right shifting by known count */
6793 /*-----------------------------------------------------------------*/
6795 genRightShiftLiteral (operand * left,
6801 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6804 D(emitcode ("; genRightShiftLiteral",""));
6806 freeAsmop (right, NULL, ic, TRUE);
6808 aopOp (left, ic, FALSE);
6809 aopOp (result, ic, FALSE);
6812 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6816 size = getDataSize (left);
6817 /* test the LEFT size !!! */
6819 /* I suppose that the left size >= result size */
6822 size = getDataSize (result);
6824 movLeft2Result (left, size, result, size, 0);
6827 else if (shCount >= (size * 8))
6830 /* get sign in acc.7 */
6831 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6832 addSign (result, LSB, sign);
6839 genrshOne (result, left, shCount, sign);
6843 genrshTwo (result, left, shCount, sign);
6847 genrshFour (result, left, shCount, sign);
6853 freeAsmop (left, NULL, ic, TRUE);
6854 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* genSignedRightShift - right shift of signed number */
6860 /*-----------------------------------------------------------------*/
6862 genSignedRightShift (iCode * ic)
6864 operand *right, *left, *result;
6867 symbol *tlbl, *tlbl1;
6869 D(emitcode ("; genSignedRightShift",""));
6871 /* we do it the hard way put the shift count in b
6872 and loop thru preserving the sign */
6874 right = IC_RIGHT (ic);
6875 left = IC_LEFT (ic);
6876 result = IC_RESULT (ic);
6878 aopOp (right, ic, FALSE);
6881 if (AOP_TYPE (right) == AOP_LIT)
6883 genRightShiftLiteral (left, right, result, ic, 1);
6886 /* shift count is unknown then we have to form
6887 a loop get the loop count in B : Note: we take
6888 only the lower order byte since shifting
6889 more that 32 bits make no sense anyway, ( the
6890 largest size of an object can be only 32 bits ) */
6892 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6893 emitcode ("inc", "b");
6894 freeAsmop (right, NULL, ic, TRUE);
6895 aopOp (left, ic, FALSE);
6896 aopOp (result, ic, FALSE);
6898 /* now move the left to the result if they are not the
6900 if (!sameRegs (AOP (left), AOP (result)) &&
6901 AOP_SIZE (result) > 1)
6904 size = AOP_SIZE (result);
6908 l = aopGet (AOP (left), offset, FALSE, TRUE);
6909 if (*l == '@' && IS_AOP_PREG (result))
6912 emitcode ("mov", "a,%s", l);
6913 aopPut (AOP (result), "a", offset);
6916 aopPut (AOP (result), l, offset);
6921 /* mov the highest order bit to OVR */
6922 tlbl = newiTempLabel (NULL);
6923 tlbl1 = newiTempLabel (NULL);
6925 size = AOP_SIZE (result);
6927 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6928 emitcode ("rlc", "a");
6929 emitcode ("mov", "ov,c");
6930 /* if it is only one byte then */
6933 l = aopGet (AOP (left), 0, FALSE, FALSE);
6935 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6936 emitcode ("", "%05d$:", tlbl->key + 100);
6937 emitcode ("mov", "c,ov");
6938 emitcode ("rrc", "a");
6939 emitcode ("", "%05d$:", tlbl1->key + 100);
6940 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6941 aopPut (AOP (result), "a", 0);
6945 reAdjustPreg (AOP (result));
6946 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6947 emitcode ("", "%05d$:", tlbl->key + 100);
6948 emitcode ("mov", "c,ov");
6951 l = aopGet (AOP (result), offset, FALSE, FALSE);
6953 emitcode ("rrc", "a");
6954 aopPut (AOP (result), "a", offset--);
6956 reAdjustPreg (AOP (result));
6957 emitcode ("", "%05d$:", tlbl1->key + 100);
6958 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6961 freeAsmop (left, NULL, ic, TRUE);
6962 freeAsmop (result, NULL, ic, TRUE);
6965 /*-----------------------------------------------------------------*/
6966 /* genRightShift - generate code for right shifting */
6967 /*-----------------------------------------------------------------*/
6969 genRightShift (iCode * ic)
6971 operand *right, *left, *result;
6975 symbol *tlbl, *tlbl1;
6977 D(emitcode ("; genRightShift",""));
6979 /* if signed then we do it the hard way preserve the
6980 sign bit moving it inwards */
6981 retype = getSpec (operandType (IC_RESULT (ic)));
6983 if (!SPEC_USIGN (retype))
6985 genSignedRightShift (ic);
6989 /* signed & unsigned types are treated the same : i.e. the
6990 signed is NOT propagated inwards : quoting from the
6991 ANSI - standard : "for E1 >> E2, is equivalent to division
6992 by 2**E2 if unsigned or if it has a non-negative value,
6993 otherwise the result is implementation defined ", MY definition
6994 is that the sign does not get propagated */
6996 right = IC_RIGHT (ic);
6997 left = IC_LEFT (ic);
6998 result = IC_RESULT (ic);
7000 aopOp (right, ic, FALSE);
7002 /* if the shift count is known then do it
7003 as efficiently as possible */
7004 if (AOP_TYPE (right) == AOP_LIT)
7006 genRightShiftLiteral (left, right, result, ic, 0);
7010 /* shift count is unknown then we have to form
7011 a loop get the loop count in B : Note: we take
7012 only the lower order byte since shifting
7013 more that 32 bits make no sense anyway, ( the
7014 largest size of an object can be only 32 bits ) */
7016 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7017 emitcode ("inc", "b");
7018 freeAsmop (right, NULL, ic, TRUE);
7019 aopOp (left, ic, FALSE);
7020 aopOp (result, ic, FALSE);
7022 /* now move the left to the result if they are not the
7024 if (!sameRegs (AOP (left), AOP (result)) &&
7025 AOP_SIZE (result) > 1)
7028 size = AOP_SIZE (result);
7032 l = aopGet (AOP (left), offset, FALSE, TRUE);
7033 if (*l == '@' && IS_AOP_PREG (result))
7036 emitcode ("mov", "a,%s", l);
7037 aopPut (AOP (result), "a", offset);
7040 aopPut (AOP (result), l, offset);
7045 tlbl = newiTempLabel (NULL);
7046 tlbl1 = newiTempLabel (NULL);
7047 size = AOP_SIZE (result);
7050 /* if it is only one byte then */
7053 l = aopGet (AOP (left), 0, FALSE, FALSE);
7055 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7056 emitcode ("", "%05d$:", tlbl->key + 100);
7058 emitcode ("rrc", "a");
7059 emitcode ("", "%05d$:", tlbl1->key + 100);
7060 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7061 aopPut (AOP (result), "a", 0);
7065 reAdjustPreg (AOP (result));
7066 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7067 emitcode ("", "%05d$:", tlbl->key + 100);
7071 l = aopGet (AOP (result), offset, FALSE, FALSE);
7073 emitcode ("rrc", "a");
7074 aopPut (AOP (result), "a", offset--);
7076 reAdjustPreg (AOP (result));
7078 emitcode ("", "%05d$:", tlbl1->key + 100);
7079 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7082 freeAsmop (left, NULL, ic, TRUE);
7083 freeAsmop (result, NULL, ic, TRUE);
7086 /*-----------------------------------------------------------------*/
7087 /* genUnpackBits - generates code for unpacking bits */
7088 /*-----------------------------------------------------------------*/
7090 genUnpackBits (operand * result, char *rname, int ptype)
7098 D(emitcode ("; genUnpackBits",""));
7100 etype = getSpec (operandType (result));
7101 rsize = getSize (operandType (result));
7102 /* read the first byte */
7108 emitcode ("mov", "a,@%s", rname);
7112 emitcode ("movx", "a,@%s", rname);
7116 emitcode ("movx", "a,@dptr");
7120 emitcode ("clr", "a");
7121 emitcode ("movc", "a,@a+dptr");
7125 emitcode ("lcall", "__gptrget");
7129 rlen = SPEC_BLEN (etype);
7131 /* if we have bitdisplacement then it fits */
7132 /* into this byte completely or if length is */
7133 /* less than a byte */
7134 if ((shCnt = SPEC_BSTR (etype)) ||
7135 (SPEC_BLEN (etype) <= 8))
7138 /* shift right acc */
7141 emitcode ("anl", "a,#0x%02x",
7142 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7143 aopPut (AOP (result), "a", offset++);
7147 /* bit field did not fit in a byte */
7148 aopPut (AOP (result), "a", offset++);
7157 emitcode ("inc", "%s", rname);
7158 emitcode ("mov", "a,@%s", rname);
7162 emitcode ("inc", "%s", rname);
7163 emitcode ("movx", "a,@%s", rname);
7167 emitcode ("inc", "dptr");
7168 emitcode ("movx", "a,@dptr");
7172 emitcode ("clr", "a");
7173 emitcode ("inc", "dptr");
7174 emitcode ("movc", "a,@a+dptr");
7178 emitcode ("inc", "dptr");
7179 emitcode ("lcall", "__gptrget");
7184 /* if we are done */
7188 aopPut (AOP (result), "a", offset++);
7194 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7196 aopPut (AOP (result), "a", offset++);
7204 aopPut (AOP (result), zero, offset++);
7210 /*-----------------------------------------------------------------*/
7211 /* genDataPointerGet - generates code when ptr offset is known */
7212 /*-----------------------------------------------------------------*/
7214 genDataPointerGet (operand * left,
7220 int size, offset = 0;
7222 D(emitcode ("; genDataPointerGet",""));
7224 aopOp (result, ic, TRUE);
7226 /* get the string representation of the name */
7227 l = aopGet (AOP (left), 0, FALSE, TRUE);
7228 size = AOP_SIZE (result);
7232 sprintf (buffer, "(%s + %d)", l + 1, offset);
7234 sprintf (buffer, "%s", l + 1);
7235 aopPut (AOP (result), buffer, offset++);
7238 freeAsmop (left, NULL, ic, TRUE);
7239 freeAsmop (result, NULL, ic, TRUE);
7242 /*-----------------------------------------------------------------*/
7243 /* genNearPointerGet - emitcode for near pointer fetch */
7244 /*-----------------------------------------------------------------*/
7246 genNearPointerGet (operand * left,
7254 sym_link *rtype, *retype;
7255 sym_link *ltype = operandType (left);
7258 D(emitcode ("; genNearPointerGet",""));
7260 rtype = operandType (result);
7261 retype = getSpec (rtype);
7263 aopOp (left, ic, FALSE);
7265 /* if left is rematerialisable and
7266 result is not bit variable type and
7267 the left is pointer to data space i.e
7268 lower 128 bytes of space */
7269 if (AOP_TYPE (left) == AOP_IMMD &&
7270 !IS_BITVAR (retype) &&
7271 DCL_TYPE (ltype) == POINTER)
7273 genDataPointerGet (left, result, ic);
7277 /* if the value is already in a pointer register
7278 then don't need anything more */
7279 if (!AOP_INPREG (AOP (left)))
7281 /* otherwise get a free pointer register */
7283 preg = getFreePtr (ic, &aop, FALSE);
7284 emitcode ("mov", "%s,%s",
7286 aopGet (AOP (left), 0, FALSE, TRUE));
7290 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7292 //aopOp (result, ic, FALSE);
7293 aopOp (result, ic, result?TRUE:FALSE);
7295 /* if bitfield then unpack the bits */
7296 if (IS_BITVAR (retype))
7297 genUnpackBits (result, rname, POINTER);
7300 /* we have can just get the values */
7301 int size = AOP_SIZE (result);
7306 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7309 emitcode ("mov", "a,@%s", rname);
7310 aopPut (AOP (result), "a", offset);
7314 sprintf (buffer, "@%s", rname);
7315 aopPut (AOP (result), buffer, offset);
7319 emitcode ("inc", "%s", rname);
7323 /* now some housekeeping stuff */
7324 if (aop) /* we had to allocate for this iCode */
7326 if (pi) { /* post increment present */
7327 aopPut(AOP ( left ),rname,0);
7329 freeAsmop (NULL, aop, ic, TRUE);
7333 /* we did not allocate which means left
7334 already in a pointer register, then
7335 if size > 0 && this could be used again
7336 we have to point it back to where it
7338 if ((AOP_SIZE (result) > 1 &&
7339 !OP_SYMBOL (left)->remat &&
7340 (OP_SYMBOL (left)->liveTo > ic->seq ||
7344 int size = AOP_SIZE (result) - 1;
7346 emitcode ("dec", "%s", rname);
7351 freeAsmop (left, NULL, ic, TRUE);
7352 freeAsmop (result, NULL, ic, TRUE);
7353 if (pi) pi->generated = 1;
7356 /*-----------------------------------------------------------------*/
7357 /* genPagedPointerGet - emitcode for paged pointer fetch */
7358 /*-----------------------------------------------------------------*/
7360 genPagedPointerGet (operand * left,
7368 sym_link *rtype, *retype;
7370 D(emitcode ("; genPagedPointerGet",""));
7372 rtype = operandType (result);
7373 retype = getSpec (rtype);
7375 aopOp (left, ic, FALSE);
7377 /* if the value is already in a pointer register
7378 then don't need anything more */
7379 if (!AOP_INPREG (AOP (left)))
7381 /* otherwise get a free pointer register */
7383 preg = getFreePtr (ic, &aop, FALSE);
7384 emitcode ("mov", "%s,%s",
7386 aopGet (AOP (left), 0, FALSE, TRUE));
7390 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7392 aopOp (result, ic, FALSE);
7394 /* if bitfield then unpack the bits */
7395 if (IS_BITVAR (retype))
7396 genUnpackBits (result, rname, PPOINTER);
7399 /* we have can just get the values */
7400 int size = AOP_SIZE (result);
7406 emitcode ("movx", "a,@%s", rname);
7407 aopPut (AOP (result), "a", offset);
7412 emitcode ("inc", "%s", rname);
7416 /* now some housekeeping stuff */
7417 if (aop) /* we had to allocate for this iCode */
7419 if (pi) aopPut ( AOP (left), rname, 0);
7420 freeAsmop (NULL, aop, ic, TRUE);
7424 /* we did not allocate which means left
7425 already in a pointer register, then
7426 if size > 0 && this could be used again
7427 we have to point it back to where it
7429 if ((AOP_SIZE (result) > 1 &&
7430 !OP_SYMBOL (left)->remat &&
7431 (OP_SYMBOL (left)->liveTo > ic->seq ||
7435 int size = AOP_SIZE (result) - 1;
7437 emitcode ("dec", "%s", rname);
7442 freeAsmop (left, NULL, ic, TRUE);
7443 freeAsmop (result, NULL, ic, TRUE);
7444 if (pi) pi->generated = 1;
7448 /*-----------------------------------------------------------------*/
7449 /* genFarPointerGet - gget value from far space */
7450 /*-----------------------------------------------------------------*/
7452 genFarPointerGet (operand * left,
7453 operand * result, iCode * ic, iCode * pi)
7456 sym_link *retype = getSpec (operandType (result));
7458 D(emitcode ("; genFarPointerGet",""));
7460 aopOp (left, ic, FALSE);
7462 /* if the operand is already in dptr
7463 then we do nothing else we move the value to dptr */
7464 if (AOP_TYPE (left) != AOP_STR)
7466 /* if this is remateriazable */
7467 if (AOP_TYPE (left) == AOP_IMMD)
7468 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7470 { /* we need to get it byte by byte */
7471 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7472 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7475 /* so dptr know contains the address */
7476 aopOp (result, ic, FALSE);
7478 /* if bit then unpack */
7479 if (IS_BITVAR (retype))
7480 genUnpackBits (result, "dptr", FPOINTER);
7483 size = AOP_SIZE (result);
7488 emitcode ("movx", "a,@dptr");
7489 aopPut (AOP (result), "a", offset++);
7491 emitcode ("inc", "dptr");
7495 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7496 aopPut ( AOP (left), "dpl", 0);
7497 aopPut ( AOP (left), "dph", 1);
7500 freeAsmop (left, NULL, ic, TRUE);
7501 freeAsmop (result, NULL, ic, TRUE);
7504 /*-----------------------------------------------------------------*/
7505 /* genCodePointerGet - gget value from code space */
7506 /*-----------------------------------------------------------------*/
7508 genCodePointerGet (operand * left,
7509 operand * result, iCode * ic, iCode *pi)
7512 sym_link *retype = getSpec (operandType (result));
7514 D(emitcode ("; genCodePointerGet",""));
7516 aopOp (left, ic, FALSE);
7518 /* if the operand is already in dptr
7519 then we do nothing else we move the value to dptr */
7520 if (AOP_TYPE (left) != AOP_STR)
7522 /* if this is remateriazable */
7523 if (AOP_TYPE (left) == AOP_IMMD)
7524 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7526 { /* we need to get it byte by byte */
7527 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7528 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7531 /* so dptr know contains the address */
7532 aopOp (result, ic, FALSE);
7534 /* if bit then unpack */
7535 if (IS_BITVAR (retype))
7536 genUnpackBits (result, "dptr", CPOINTER);
7539 size = AOP_SIZE (result);
7544 emitcode ("clr", "a");
7545 emitcode ("movc", "a,@a+dptr");
7546 aopPut (AOP (result), "a", offset++);
7548 emitcode ("inc", "dptr");
7552 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7553 aopPut ( AOP (left), "dpl", 0);
7554 aopPut ( AOP (left), "dph", 1);
7557 freeAsmop (left, NULL, ic, TRUE);
7558 freeAsmop (result, NULL, ic, TRUE);
7561 /*-----------------------------------------------------------------*/
7562 /* genGenPointerGet - gget value from generic pointer space */
7563 /*-----------------------------------------------------------------*/
7565 genGenPointerGet (operand * left,
7566 operand * result, iCode * ic, iCode *pi)
7569 sym_link *retype = getSpec (operandType (result));
7571 D(emitcode ("; genGenPointerGet",""));
7573 aopOp (left, ic, FALSE);
7575 /* if the operand is already in dptr
7576 then we do nothing else we move the value to dptr */
7577 if (AOP_TYPE (left) != AOP_STR)
7579 /* if this is remateriazable */
7580 if (AOP_TYPE (left) == AOP_IMMD)
7582 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7583 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7584 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7586 emitcode ("mov", "b,#%d", pointerCode (retype));
7589 { /* we need to get it byte by byte */
7590 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7591 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7592 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7595 /* so dptr know contains the address */
7596 aopOp (result, ic, FALSE);
7598 /* if bit then unpack */
7599 if (IS_BITVAR (retype))
7600 genUnpackBits (result, "dptr", GPOINTER);
7603 size = AOP_SIZE (result);
7608 emitcode ("lcall", "__gptrget");
7609 aopPut (AOP (result), "a", offset++);
7611 emitcode ("inc", "dptr");
7615 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7616 aopPut ( AOP (left), "dpl", 0);
7617 aopPut ( AOP (left), "dph", 1);
7618 aopPut ( AOP (left), "b", 2);
7621 freeAsmop (left, NULL, ic, TRUE);
7622 freeAsmop (result, NULL, ic, TRUE);
7625 /*-----------------------------------------------------------------*/
7626 /* genPointerGet - generate code for pointer get */
7627 /*-----------------------------------------------------------------*/
7629 genPointerGet (iCode * ic, iCode *pi)
7631 operand *left, *result;
7632 sym_link *type, *etype;
7635 D(emitcode ("; genPointerGet",""));
7637 left = IC_LEFT (ic);
7638 result = IC_RESULT (ic);
7640 /* depending on the type of pointer we need to
7641 move it to the correct pointer register */
7642 type = operandType (left);
7643 etype = getSpec (type);
7644 /* if left is of type of pointer then it is simple */
7645 if (IS_PTR (type) && !IS_FUNC (type->next))
7646 p_type = DCL_TYPE (type);
7649 /* we have to go by the storage class */
7650 p_type = PTR_TYPE (SPEC_OCLS (etype));
7653 /* special case when cast remat */
7654 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7655 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7656 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7657 type = operandType (left);
7658 p_type = DCL_TYPE (type);
7660 /* now that we have the pointer type we assign
7661 the pointer values */
7667 genNearPointerGet (left, result, ic, pi);
7671 genPagedPointerGet (left, result, ic, pi);
7675 genFarPointerGet (left, result, ic, pi);
7679 genCodePointerGet (left, result, ic, pi);
7683 genGenPointerGet (left, result, ic, pi);
7689 /*-----------------------------------------------------------------*/
7690 /* genPackBits - generates code for packed bit storage */
7691 /*-----------------------------------------------------------------*/
7693 genPackBits (sym_link * etype,
7695 char *rname, int p_type)
7703 D(emitcode ("; genPackBits",""));
7705 blen = SPEC_BLEN (etype);
7706 bstr = SPEC_BSTR (etype);
7708 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7711 /* if the bit lenth is less than or */
7712 /* it exactly fits a byte then */
7713 if (SPEC_BLEN (etype) <= 8)
7715 shCount = SPEC_BSTR (etype);
7717 /* shift left acc */
7720 if (SPEC_BLEN (etype) < 8)
7721 { /* if smaller than a byte */
7727 emitcode ("mov", "b,a");
7728 emitcode ("mov", "a,@%s", rname);
7732 emitcode ("mov", "b,a");
7733 emitcode ("movx", "a,@dptr");
7737 emitcode ("push", "b");
7738 emitcode ("push", "acc");
7739 emitcode ("lcall", "__gptrget");
7740 emitcode ("pop", "b");
7744 emitcode ("anl", "a,#0x%02x", (unsigned char)
7745 ((unsigned char) (0xFF << (blen + bstr)) |
7746 (unsigned char) (0xFF >> (8 - bstr))));
7747 emitcode ("orl", "a,b");
7748 if (p_type == GPOINTER)
7749 emitcode ("pop", "b");
7756 emitcode ("mov", "@%s,a", rname);
7760 emitcode ("movx", "@dptr,a");
7764 emitcode ("lcall", "__gptrput");
7769 if (SPEC_BLEN (etype) <= 8)
7772 emitcode ("inc", "%s", rname);
7773 rLen = SPEC_BLEN (etype);
7775 /* now generate for lengths greater than one byte */
7779 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7791 emitcode ("mov", "@%s,a", rname);
7794 emitcode ("mov", "@%s,%s", rname, l);
7799 emitcode ("movx", "@dptr,a");
7804 emitcode ("lcall", "__gptrput");
7807 emitcode ("inc", "%s", rname);
7812 /* last last was not complete */
7815 /* save the byte & read byte */
7819 emitcode ("mov", "b,a");
7820 emitcode ("mov", "a,@%s", rname);
7824 emitcode ("mov", "b,a");
7825 emitcode ("movx", "a,@dptr");
7829 emitcode ("push", "b");
7830 emitcode ("push", "acc");
7831 emitcode ("lcall", "__gptrget");
7832 emitcode ("pop", "b");
7836 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7837 emitcode ("orl", "a,b");
7840 if (p_type == GPOINTER)
7841 emitcode ("pop", "b");
7847 emitcode ("mov", "@%s,a", rname);
7851 emitcode ("movx", "@dptr,a");
7855 emitcode ("lcall", "__gptrput");
7859 /*-----------------------------------------------------------------*/
7860 /* genDataPointerSet - remat pointer to data space */
7861 /*-----------------------------------------------------------------*/
7863 genDataPointerSet (operand * right,
7867 int size, offset = 0;
7868 char *l, buffer[256];
7870 D(emitcode ("; genDataPointerSet",""));
7872 aopOp (right, ic, FALSE);
7874 l = aopGet (AOP (result), 0, FALSE, TRUE);
7875 size = AOP_SIZE (right);
7879 sprintf (buffer, "(%s + %d)", l + 1, offset);
7881 sprintf (buffer, "%s", l + 1);
7882 emitcode ("mov", "%s,%s", buffer,
7883 aopGet (AOP (right), offset++, FALSE, FALSE));
7886 freeAsmop (right, NULL, ic, TRUE);
7887 freeAsmop (result, NULL, ic, TRUE);
7890 /*-----------------------------------------------------------------*/
7891 /* genNearPointerSet - emitcode for near pointer put */
7892 /*-----------------------------------------------------------------*/
7894 genNearPointerSet (operand * right,
7902 sym_link *retype, *letype;
7903 sym_link *ptype = operandType (result);
7905 D(emitcode ("; genNearPointerSet",""));
7907 retype = getSpec (operandType (right));
7908 letype = getSpec (ptype);
7909 aopOp (result, ic, FALSE);
7911 /* if the result is rematerializable &
7912 in data space & not a bit variable */
7913 if (AOP_TYPE (result) == AOP_IMMD &&
7914 DCL_TYPE (ptype) == POINTER &&
7915 !IS_BITVAR (retype) &&
7916 !IS_BITVAR (letype))
7918 genDataPointerSet (right, result, ic);
7922 /* if the value is already in a pointer register
7923 then don't need anything more */
7924 if (!AOP_INPREG (AOP (result)))
7927 //AOP_TYPE (result) == AOP_STK
7931 // Aha, it is a pointer, just in disguise.
7932 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7935 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7936 __FILE__, __LINE__);
7941 rname++; // skip the '@'.
7946 /* otherwise get a free pointer register */
7948 preg = getFreePtr (ic, &aop, FALSE);
7949 emitcode ("mov", "%s,%s",
7951 aopGet (AOP (result), 0, FALSE, TRUE));
7957 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7960 aopOp (right, ic, FALSE);
7962 /* if bitfield then unpack the bits */
7963 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7964 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7967 /* we have can just get the values */
7968 int size = AOP_SIZE (right);
7973 l = aopGet (AOP (right), offset, FALSE, TRUE);
7977 emitcode ("mov", "@%s,a", rname);
7980 emitcode ("mov", "@%s,%s", rname, l);
7982 emitcode ("inc", "%s", rname);
7987 /* now some housekeeping stuff */
7988 if (aop) /* we had to allocate for this iCode */
7990 if (pi) aopPut (AOP (result),rname,0);
7991 freeAsmop (NULL, aop, ic, TRUE);
7995 /* we did not allocate which means left
7996 already in a pointer register, then
7997 if size > 0 && this could be used again
7998 we have to point it back to where it
8000 if ((AOP_SIZE (right) > 1 &&
8001 !OP_SYMBOL (result)->remat &&
8002 (OP_SYMBOL (result)->liveTo > ic->seq ||
8006 int size = AOP_SIZE (right) - 1;
8008 emitcode ("dec", "%s", rname);
8013 if (pi) pi->generated = 1;
8014 freeAsmop (result, NULL, ic, TRUE);
8015 freeAsmop (right, NULL, ic, TRUE);
8018 /*-----------------------------------------------------------------*/
8019 /* genPagedPointerSet - emitcode for Paged pointer put */
8020 /*-----------------------------------------------------------------*/
8022 genPagedPointerSet (operand * right,
8030 sym_link *retype, *letype;
8032 D(emitcode ("; genPagedPointerSet",""));
8034 retype = getSpec (operandType (right));
8035 letype = getSpec (operandType (result));
8037 aopOp (result, ic, FALSE);
8039 /* if the value is already in a pointer register
8040 then don't need anything more */
8041 if (!AOP_INPREG (AOP (result)))
8043 /* otherwise get a free pointer register */
8045 preg = getFreePtr (ic, &aop, FALSE);
8046 emitcode ("mov", "%s,%s",
8048 aopGet (AOP (result), 0, FALSE, TRUE));
8052 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8054 aopOp (right, ic, FALSE);
8056 /* if bitfield then unpack the bits */
8057 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8058 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8061 /* we have can just get the values */
8062 int size = AOP_SIZE (right);
8067 l = aopGet (AOP (right), offset, FALSE, TRUE);
8070 emitcode ("movx", "@%s,a", rname);
8073 emitcode ("inc", "%s", rname);
8079 /* now some housekeeping stuff */
8080 if (aop) /* we had to allocate for this iCode */
8082 if (pi) aopPut (AOP (result),rname,0);
8083 freeAsmop (NULL, aop, ic, TRUE);
8087 /* we did not allocate which means left
8088 already in a pointer register, then
8089 if size > 0 && this could be used again
8090 we have to point it back to where it
8092 if (AOP_SIZE (right) > 1 &&
8093 !OP_SYMBOL (result)->remat &&
8094 (OP_SYMBOL (result)->liveTo > ic->seq ||
8097 int size = AOP_SIZE (right) - 1;
8099 emitcode ("dec", "%s", rname);
8104 if (pi) pi->generated = 1;
8105 freeAsmop (result, NULL, ic, TRUE);
8106 freeAsmop (right, NULL, ic, TRUE);
8111 /*-----------------------------------------------------------------*/
8112 /* genFarPointerSet - set value from far space */
8113 /*-----------------------------------------------------------------*/
8115 genFarPointerSet (operand * right,
8116 operand * result, iCode * ic, iCode * pi)
8119 sym_link *retype = getSpec (operandType (right));
8120 sym_link *letype = getSpec (operandType (result));
8122 D(emitcode ("; genFarPointerSet",""));
8124 aopOp (result, ic, FALSE);
8126 /* if the operand is already in dptr
8127 then we do nothing else we move the value to dptr */
8128 if (AOP_TYPE (result) != AOP_STR)
8130 /* if this is remateriazable */
8131 if (AOP_TYPE (result) == AOP_IMMD)
8132 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8134 { /* we need to get it byte by byte */
8135 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8136 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8139 /* so dptr know contains the address */
8140 aopOp (right, ic, FALSE);
8142 /* if bit then unpack */
8143 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8144 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8147 size = AOP_SIZE (right);
8152 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8154 emitcode ("movx", "@dptr,a");
8156 emitcode ("inc", "dptr");
8159 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8160 aopPut (AOP(result),"dpl",0);
8161 aopPut (AOP(result),"dph",1);
8164 freeAsmop (result, NULL, ic, TRUE);
8165 freeAsmop (right, NULL, ic, TRUE);
8168 /*-----------------------------------------------------------------*/
8169 /* genGenPointerSet - set value from generic pointer space */
8170 /*-----------------------------------------------------------------*/
8172 genGenPointerSet (operand * right,
8173 operand * result, iCode * ic, iCode * pi)
8176 sym_link *retype = getSpec (operandType (right));
8177 sym_link *letype = getSpec (operandType (result));
8179 D(emitcode ("; genGenPointerSet",""));
8181 aopOp (result, ic, FALSE);
8183 /* if the operand is already in dptr
8184 then we do nothing else we move the value to dptr */
8185 if (AOP_TYPE (result) != AOP_STR)
8187 /* if this is remateriazable */
8188 if (AOP_TYPE (result) == AOP_IMMD)
8190 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8191 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8192 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8194 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8197 { /* we need to get it byte by byte */
8198 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8199 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8200 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8203 /* so dptr know contains the address */
8204 aopOp (right, ic, FALSE);
8206 /* if bit then unpack */
8207 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8208 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8211 size = AOP_SIZE (right);
8216 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8218 emitcode ("lcall", "__gptrput");
8220 emitcode ("inc", "dptr");
8224 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8225 aopPut (AOP(result),"dpl",0);
8226 aopPut (AOP(result),"dph",1);
8227 aopPut (AOP(result),"b",2);
8230 freeAsmop (result, NULL, ic, TRUE);
8231 freeAsmop (right, NULL, ic, TRUE);
8234 /*-----------------------------------------------------------------*/
8235 /* genPointerSet - stores the value into a pointer location */
8236 /*-----------------------------------------------------------------*/
8238 genPointerSet (iCode * ic, iCode *pi)
8240 operand *right, *result;
8241 sym_link *type, *etype;
8244 D(emitcode ("; genPointerSet",""));
8246 right = IC_RIGHT (ic);
8247 result = IC_RESULT (ic);
8249 /* depending on the type of pointer we need to
8250 move it to the correct pointer register */
8251 type = operandType (result);
8252 etype = getSpec (type);
8253 /* if left is of type of pointer then it is simple */
8254 if (IS_PTR (type) && !IS_FUNC (type->next))
8256 p_type = DCL_TYPE (type);
8260 /* we have to go by the storage class */
8261 p_type = PTR_TYPE (SPEC_OCLS (etype));
8264 /* special case when cast remat */
8265 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8266 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8267 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8268 type = operandType (result);
8269 p_type = DCL_TYPE (type);
8271 /* now that we have the pointer type we assign
8272 the pointer values */
8278 genNearPointerSet (right, result, ic, pi);
8282 genPagedPointerSet (right, result, ic, pi);
8286 genFarPointerSet (right, result, ic, pi);
8290 genGenPointerSet (right, result, ic, pi);
8294 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8295 "genPointerSet: illegal pointer type");
8300 /*-----------------------------------------------------------------*/
8301 /* genIfx - generate code for Ifx statement */
8302 /*-----------------------------------------------------------------*/
8304 genIfx (iCode * ic, iCode * popIc)
8306 operand *cond = IC_COND (ic);
8309 D(emitcode ("; genIfx",""));
8311 aopOp (cond, ic, FALSE);
8313 /* get the value into acc */
8314 if (AOP_TYPE (cond) != AOP_CRY)
8318 /* the result is now in the accumulator */
8319 freeAsmop (cond, NULL, ic, TRUE);
8321 /* if there was something to be popped then do it */
8325 /* if the condition is a bit variable */
8326 if (isbit && IS_ITEMP (cond) &&
8328 genIfxJump (ic, SPIL_LOC (cond)->rname);
8329 else if (isbit && !IS_ITEMP (cond))
8330 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8332 genIfxJump (ic, "a");
8337 /*-----------------------------------------------------------------*/
8338 /* genAddrOf - generates code for address of */
8339 /*-----------------------------------------------------------------*/
8341 genAddrOf (iCode * ic)
8343 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8346 D(emitcode ("; genAddrOf",""));
8348 aopOp (IC_RESULT (ic), ic, FALSE);
8350 /* if the operand is on the stack then we
8351 need to get the stack offset of this
8355 /* if it has an offset then we need to compute
8359 emitcode ("mov", "a,_bp");
8360 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8361 ((char) (sym->stack - _G.nRegsSaved)) :
8362 ((char) sym->stack)) & 0xff);
8363 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8367 /* we can just move _bp */
8368 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8370 /* fill the result with zero */
8371 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8376 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8382 /* object not on stack then we need the name */
8383 size = AOP_SIZE (IC_RESULT (ic));
8388 char s[SDCC_NAME_MAX];
8390 sprintf (s, "#(%s >> %d)",
8394 sprintf (s, "#%s", sym->rname);
8395 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8399 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8403 /*-----------------------------------------------------------------*/
8404 /* genFarFarAssign - assignment when both are in far space */
8405 /*-----------------------------------------------------------------*/
8407 genFarFarAssign (operand * result, operand * right, iCode * ic)
8409 int size = AOP_SIZE (right);
8413 D(emitcode ("; genFarFarAssign",""));
8415 /* first push the right side on to the stack */
8418 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8420 emitcode ("push", "acc");
8423 freeAsmop (right, NULL, ic, FALSE);
8424 /* now assign DPTR to result */
8425 aopOp (result, ic, FALSE);
8426 size = AOP_SIZE (result);
8429 emitcode ("pop", "acc");
8430 aopPut (AOP (result), "a", --offset);
8432 freeAsmop (result, NULL, ic, FALSE);
8436 /*-----------------------------------------------------------------*/
8437 /* genAssign - generate code for assignment */
8438 /*-----------------------------------------------------------------*/
8440 genAssign (iCode * ic)
8442 operand *result, *right;
8444 unsigned long lit = 0L;
8446 D(emitcode("; genAssign",""));
8448 result = IC_RESULT (ic);
8449 right = IC_RIGHT (ic);
8451 /* if they are the same */
8452 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8455 aopOp (right, ic, FALSE);
8457 /* special case both in far space */
8458 if (AOP_TYPE (right) == AOP_DPTR &&
8459 IS_TRUE_SYMOP (result) &&
8460 isOperandInFarSpace (result))
8463 genFarFarAssign (result, right, ic);
8467 aopOp (result, ic, TRUE);
8469 /* if they are the same registers */
8470 if (sameRegs (AOP (right), AOP (result)))
8473 /* if the result is a bit */
8474 if (AOP_TYPE (result) == AOP_CRY)
8477 /* if the right size is a literal then
8478 we know what the value is */
8479 if (AOP_TYPE (right) == AOP_LIT)
8481 if (((int) operandLitValue (right)))
8482 aopPut (AOP (result), one, 0);
8484 aopPut (AOP (result), zero, 0);
8488 /* the right is also a bit variable */
8489 if (AOP_TYPE (right) == AOP_CRY)
8491 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8492 aopPut (AOP (result), "c", 0);
8498 aopPut (AOP (result), "a", 0);
8502 /* bit variables done */
8504 size = AOP_SIZE (result);
8506 if (AOP_TYPE (right) == AOP_LIT)
8507 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8509 (AOP_TYPE (result) != AOP_REG) &&
8510 (AOP_TYPE (right) == AOP_LIT) &&
8511 !IS_FLOAT (operandType (right)) &&
8514 emitcode ("clr", "a");
8517 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8518 aopPut (AOP (result), "a", size);
8520 aopPut (AOP (result),
8521 aopGet (AOP (right), size, FALSE, FALSE),
8529 aopPut (AOP (result),
8530 aopGet (AOP (right), offset, FALSE, FALSE),
8537 freeAsmop (right, NULL, ic, TRUE);
8538 freeAsmop (result, NULL, ic, TRUE);
8541 /*-----------------------------------------------------------------*/
8542 /* genJumpTab - genrates code for jump table */
8543 /*-----------------------------------------------------------------*/
8545 genJumpTab (iCode * ic)
8550 D(emitcode ("; genJumpTab",""));
8552 aopOp (IC_JTCOND (ic), ic, FALSE);
8553 /* get the condition into accumulator */
8554 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8556 /* multiply by three */
8557 emitcode ("add", "a,acc");
8558 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8559 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8561 jtab = newiTempLabel (NULL);
8562 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8563 emitcode ("jmp", "@a+dptr");
8564 emitcode ("", "%05d$:", jtab->key + 100);
8565 /* now generate the jump labels */
8566 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8567 jtab = setNextItem (IC_JTLABELS (ic)))
8568 emitcode ("ljmp", "%05d$", jtab->key + 100);
8572 /*-----------------------------------------------------------------*/
8573 /* genCast - gen code for casting */
8574 /*-----------------------------------------------------------------*/
8576 genCast (iCode * ic)
8578 operand *result = IC_RESULT (ic);
8579 sym_link *ctype = operandType (IC_LEFT (ic));
8580 sym_link *rtype = operandType (IC_RIGHT (ic));
8581 operand *right = IC_RIGHT (ic);
8584 D(emitcode("; genCast",""));
8586 /* if they are equivalent then do nothing */
8587 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8590 aopOp (right, ic, FALSE);
8591 aopOp (result, ic, FALSE);
8593 /* if the result is a bit */
8594 if (IS_BITVAR(OP_SYMBOL(result)->type))
8596 /* if the right size is a literal then
8597 we know what the value is */
8598 if (AOP_TYPE (right) == AOP_LIT)
8600 if (((int) operandLitValue (right)))
8601 aopPut (AOP (result), one, 0);
8603 aopPut (AOP (result), zero, 0);
8608 /* the right is also a bit variable */
8609 if (AOP_TYPE (right) == AOP_CRY)
8611 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8612 aopPut (AOP (result), "c", 0);
8618 aopPut (AOP (result), "a", 0);
8622 /* if they are the same size : or less */
8623 if (AOP_SIZE (result) <= AOP_SIZE (right))
8626 /* if they are in the same place */
8627 if (sameRegs (AOP (right), AOP (result)))
8630 /* if they in different places then copy */
8631 size = AOP_SIZE (result);
8635 aopPut (AOP (result),
8636 aopGet (AOP (right), offset, FALSE, FALSE),
8644 /* if the result is of type pointer */
8649 sym_link *type = operandType (right);
8650 sym_link *etype = getSpec (type);
8652 /* pointer to generic pointer */
8653 if (IS_GENPTR (ctype))
8656 p_type = DCL_TYPE (type);
8659 if (SPEC_SCLS(etype)==S_REGISTER) {
8660 // let's assume it is a generic pointer
8663 /* we have to go by the storage class */
8664 p_type = PTR_TYPE (SPEC_OCLS (etype));
8668 /* the first two bytes are known */
8669 size = GPTRSIZE - 1;
8673 aopPut (AOP (result),
8674 aopGet (AOP (right), offset, FALSE, FALSE),
8678 /* the last byte depending on type */
8680 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8685 // pointerTypeToGPByte will have bitched.
8689 sprintf(gpValStr, "#0x%d", gpVal);
8690 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8695 /* just copy the pointers */
8696 size = AOP_SIZE (result);
8700 aopPut (AOP (result),
8701 aopGet (AOP (right), offset, FALSE, FALSE),
8708 /* so we now know that the size of destination is greater
8709 than the size of the source */
8710 /* we move to result for the size of source */
8711 size = AOP_SIZE (right);
8715 aopPut (AOP (result),
8716 aopGet (AOP (right), offset, FALSE, FALSE),
8721 /* now depending on the sign of the source && destination */
8722 size = AOP_SIZE (result) - AOP_SIZE (right);
8723 /* if unsigned or not an integral type */
8724 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8727 aopPut (AOP (result), zero, offset++);
8731 /* we need to extend the sign :{ */
8732 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8735 emitcode ("rlc", "a");
8736 emitcode ("subb", "a,acc");
8738 aopPut (AOP (result), "a", offset++);
8741 /* we are done hurray !!!! */
8744 freeAsmop (right, NULL, ic, TRUE);
8745 freeAsmop (result, NULL, ic, TRUE);
8749 /*-----------------------------------------------------------------*/
8750 /* genDjnz - generate decrement & jump if not zero instrucion */
8751 /*-----------------------------------------------------------------*/
8753 genDjnz (iCode * ic, iCode * ifx)
8759 D(emitcode ("; genDjnz",""));
8761 /* if the if condition has a false label
8762 then we cannot save */
8766 /* if the minus is not of the form
8768 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8769 !IS_OP_LITERAL (IC_RIGHT (ic)))
8772 if (operandLitValue (IC_RIGHT (ic)) != 1)
8775 /* if the size of this greater than one then no
8777 if (getSize (operandType (IC_RESULT (ic))) > 1)
8780 /* otherwise we can save BIG */
8781 lbl = newiTempLabel (NULL);
8782 lbl1 = newiTempLabel (NULL);
8784 aopOp (IC_RESULT (ic), ic, FALSE);
8786 if (AOP_NEEDSACC(IC_RESULT(ic)))
8788 /* If the result is accessed indirectly via
8789 * the accumulator, we must explicitly write
8790 * it back after the decrement.
8792 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8794 if (strcmp(rByte, "a"))
8796 /* Something is hopelessly wrong */
8797 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8798 __FILE__, __LINE__);
8799 /* We can just give up; the generated code will be inefficient,
8802 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8805 emitcode ("dec", "%s", rByte);
8806 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8807 emitcode ("jnz", "%05d$", lbl->key + 100);
8809 else if (IS_AOP_PREG (IC_RESULT (ic)))
8811 emitcode ("dec", "%s",
8812 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8813 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8814 emitcode ("jnz", "%05d$", lbl->key + 100);
8818 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8821 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8822 emitcode ("", "%05d$:", lbl->key + 100);
8823 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8824 emitcode ("", "%05d$:", lbl1->key + 100);
8826 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8831 /*-----------------------------------------------------------------*/
8832 /* genReceive - generate code for a receive iCode */
8833 /*-----------------------------------------------------------------*/
8835 genReceive (iCode * ic)
8837 int size = getSize (operandType (IC_RESULT (ic)));
8839 D(emitcode ("; genReceive",""));
8841 if (ic->argreg == 1) { /* first parameter */
8842 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8843 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8844 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8846 offset = fReturnSizeMCS51 - size;
8848 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8849 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8852 aopOp (IC_RESULT (ic), ic, FALSE);
8853 size = AOP_SIZE (IC_RESULT (ic));
8856 emitcode ("pop", "acc");
8857 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8862 aopOp (IC_RESULT (ic), ic, FALSE);
8864 assignResultValue (IC_RESULT (ic));
8866 } else { /* second receive onwards */
8868 aopOp (IC_RESULT (ic), ic, FALSE);
8869 rb1off = ic->argreg;
8871 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8877 /*-----------------------------------------------------------------*/
8878 /* gen51Code - generate code for 8051 based controllers */
8879 /*-----------------------------------------------------------------*/
8881 gen51Code (iCode * lic)
8886 lineHead = lineCurr = NULL;
8888 /* print the allocation information */
8890 printAllocInfo (currFunc, codeOutFile);
8891 /* if debug information required */
8892 if (options.debug && currFunc)
8894 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8896 if (IS_STATIC (currFunc->etype))
8897 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8899 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8902 /* stack pointer name */
8903 if (options.useXstack)
8909 for (ic = lic; ic; ic = ic->next)
8912 if (ic->lineno && cln != ic->lineno)
8917 emitcode ("", "C$%s$%d$%d$%d ==.",
8918 FileBaseName (ic->filename), ic->lineno,
8919 ic->level, ic->block);
8922 emitcode ("", "; %s:%d: %s", ic->filename, ic->lineno,
8923 printCLine(ic->filename, ic->lineno));
8926 /* if the result is marked as
8927 spilt and rematerializable or code for
8928 this has already been generated then
8930 if (resultRemat (ic) || ic->generated)
8933 /* depending on the operation */
8953 /* IPOP happens only when trying to restore a
8954 spilt live range, if there is an ifx statement
8955 following this pop then the if statement might
8956 be using some of the registers being popped which
8957 would destory the contents of the register so
8958 we need to check for this condition and handle it */
8960 ic->next->op == IFX &&
8961 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8962 genIfx (ic->next, ic);
8980 genEndFunction (ic);
9000 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9017 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9021 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9028 /* note these two are xlated by algebraic equivalence
9029 during parsing SDCC.y */
9030 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9031 "got '>=' or '<=' shouldn't have come here");
9035 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9047 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9051 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9055 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9082 case GET_VALUE_AT_ADDRESS:
9083 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9087 if (POINTER_SET (ic))
9088 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9114 addSet (&_G.sendSet, ic);
9123 /* now we are ready to call the
9124 peep hole optimizer */
9125 if (!options.nopeep)
9126 peepHole (&lineHead);
9128 /* now do the actual printing */
9129 printLine (lineHead, codeOutFile);