1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 static char *rb1regs[] = {
97 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
104 #define RESULTONSTACK(x) \
105 (IC_RESULT(x) && IC_RESULT(x)->aop && \
106 IC_RESULT(x)->aop->type == AOP_STK )
108 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
109 #define CLRC emitcode("clr","c")
110 #define SETC emitcode("setb","c")
112 static lineNode *lineHead = NULL;
113 static lineNode *lineCurr = NULL;
115 static unsigned char SLMask[] =
116 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char SRMask[] =
119 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
120 0x07, 0x03, 0x01, 0x00};
127 /*-----------------------------------------------------------------*/
128 /* emitcode - writes the code into a file : for now it is simple */
129 /*-----------------------------------------------------------------*/
131 emitcode (char *inst, char *fmt,...)
134 char lb[INITIAL_INLINEASM];
142 sprintf (lb, "%s\t", inst);
144 sprintf (lb, "%s", inst);
145 vsprintf (lb + (strlen (lb)), fmt, ap);
148 vsprintf (lb, fmt, ap);
150 while (isspace (*lbp))
154 lineCurr = (lineCurr ?
155 connectLine (lineCurr, newLineNode (lb)) :
156 (lineHead = newLineNode (lb)));
157 lineCurr->isInline = _G.inLine;
158 lineCurr->isDebug = _G.debugLine;
162 /*-----------------------------------------------------------------*/
163 /* mova - moves specified value into accumulator */
164 /*-----------------------------------------------------------------*/
168 /* do some early peephole optimization */
169 if (!strcmp(x, "a") || !strcmp(x, "acc"))
172 emitcode("mov","a,%s", x);
175 /*-----------------------------------------------------------------*/
176 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
177 /*-----------------------------------------------------------------*/
179 getFreePtr (iCode * ic, asmop ** aopp, bool result)
181 bool r0iu = FALSE, r1iu = FALSE;
182 bool r0ou = FALSE, r1ou = FALSE;
184 /* the logic: if r0 & r1 used in the instruction
185 then we are in trouble otherwise */
187 /* first check if r0 & r1 are used by this
188 instruction, in which case we are in trouble */
189 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
190 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
195 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
196 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
198 /* if no usage of r0 then return it */
201 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
202 (*aopp)->type = AOP_R0;
204 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
207 /* if no usage of r1 then return it */
210 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
211 (*aopp)->type = AOP_R1;
213 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
216 /* now we know they both have usage */
217 /* if r0 not used in this instruction */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 mcs51_regWithIdx (R0_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
229 (*aopp)->type = AOP_R0;
231 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
234 /* if r1 not used then */
238 /* push it if not already pushed */
241 emitcode ("push", "%s",
242 mcs51_regWithIdx (R1_IDX)->dname);
246 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
247 (*aopp)->type = AOP_R1;
248 return mcs51_regWithIdx (R1_IDX);
252 /* I said end of world but not quite end of world yet */
253 /* if this is a result then we can push it on the stack */
256 (*aopp)->type = AOP_STK;
260 /* other wise this is true end of the world */
261 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
262 "getFreePtr should never reach here");
266 /*-----------------------------------------------------------------*/
267 /* newAsmop - creates a new asmOp */
268 /*-----------------------------------------------------------------*/
270 newAsmop (short type)
274 aop = Safe_calloc (1, sizeof (asmop));
279 /*-----------------------------------------------------------------*/
280 /* pointerCode - returns the code for a pointer type */
281 /*-----------------------------------------------------------------*/
283 pointerCode (sym_link * etype)
286 return PTR_TYPE (SPEC_OCLS (etype));
290 /*-----------------------------------------------------------------*/
291 /* aopForSym - for a true symbol */
292 /*-----------------------------------------------------------------*/
294 aopForSym (iCode * ic, symbol * sym, bool result)
299 wassertl (ic != NULL, "Got a null iCode");
300 wassertl (sym != NULL, "Got a null symbol");
302 space = SPEC_OCLS (sym->etype);
304 /* if already has one */
308 /* assign depending on the storage class */
309 /* if it is on the stack or indirectly addressable */
310 /* space we need to assign either r0 or r1 to it */
311 if (sym->onStack || sym->iaccess)
313 sym->aop = aop = newAsmop (0);
314 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
315 aop->size = getSize (sym->type);
317 /* now assign the address of the variable to
318 the pointer register */
319 if (aop->type != AOP_STK)
325 emitcode ("push", "acc");
327 emitcode ("mov", "a,_bp");
328 emitcode ("add", "a,#0x%02x",
330 ((char) (sym->stack - _G.nRegsSaved)) :
331 ((char) sym->stack)) & 0xff);
332 emitcode ("mov", "%s,a",
333 aop->aopu.aop_ptr->name);
336 emitcode ("pop", "acc");
339 emitcode ("mov", "%s,#%s",
340 aop->aopu.aop_ptr->name,
342 aop->paged = space->paged;
345 aop->aopu.aop_stk = sym->stack;
349 /* if in bit space */
350 if (IN_BITSPACE (space))
352 sym->aop = aop = newAsmop (AOP_CRY);
353 aop->aopu.aop_dir = sym->rname;
354 aop->size = getSize (sym->type);
357 /* if it is in direct space */
358 if (IN_DIRSPACE (space))
360 sym->aop = aop = newAsmop (AOP_DIR);
361 aop->aopu.aop_dir = sym->rname;
362 aop->size = getSize (sym->type);
366 /* special case for a function */
367 if (IS_FUNC (sym->type))
369 sym->aop = aop = newAsmop (AOP_IMMD);
370 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
371 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop (AOP_DPTR);
379 emitcode ("mov", "dptr,#%s", sym->rname);
380 aop->size = getSize (sym->type);
382 /* if it is in code space */
383 if (IN_CODESPACE (space))
389 /*-----------------------------------------------------------------*/
390 /* aopForRemat - rematerialzes an object */
391 /*-----------------------------------------------------------------*/
393 aopForRemat (symbol * sym)
395 iCode *ic = sym->rematiCode;
396 asmop *aop = newAsmop (AOP_IMMD);
403 val += (int) operandLitValue (IC_RIGHT (ic));
404 else if (ic->op == '-')
405 val -= (int) operandLitValue (IC_RIGHT (ic));
406 else if (IS_CAST_ICODE(ic)) {
407 sym_link *from_type = operandType(IC_RIGHT(ic));
408 aop->aopu.aop_immd.from_cast_remat = 1;
409 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
410 ptr_type = DCL_TYPE(from_type);
411 if (ptr_type == IPOINTER) {
418 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
422 sprintf (buffer, "(%s %c 0x%04x)",
423 OP_SYMBOL (IC_LEFT (ic))->rname,
424 val >= 0 ? '+' : '-',
427 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
429 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
430 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
431 /* set immd2 field if required */
432 if (aop->aopu.aop_immd.from_cast_remat) {
433 sprintf(buffer,"#0x%02x",ptr_type);
434 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
435 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
441 /*-----------------------------------------------------------------*/
442 /* regsInCommon - two operands have some registers in common */
443 /*-----------------------------------------------------------------*/
445 regsInCommon (operand * op1, operand * op2)
450 /* if they have registers in common */
451 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
454 sym1 = OP_SYMBOL (op1);
455 sym2 = OP_SYMBOL (op2);
457 if (sym1->nRegs == 0 || sym2->nRegs == 0)
460 for (i = 0; i < sym1->nRegs; i++)
466 for (j = 0; j < sym2->nRegs; j++)
471 if (sym2->regs[j] == sym1->regs[i])
479 /*-----------------------------------------------------------------*/
480 /* operandsEqu - equivalent */
481 /*-----------------------------------------------------------------*/
483 operandsEqu (operand * op1, operand * op2)
487 /* if they not symbols */
488 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
491 sym1 = OP_SYMBOL (op1);
492 sym2 = OP_SYMBOL (op2);
494 /* if both are itemps & one is spilt
495 and the other is not then false */
496 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
497 sym1->isspilt != sym2->isspilt)
500 /* if they are the same */
504 if (strcmp (sym1->rname, sym2->rname) == 0)
508 /* if left is a tmp & right is not */
509 if (IS_ITEMP (op1) &&
512 (sym1->usl.spillLoc == sym2))
515 if (IS_ITEMP (op2) &&
519 (sym2->usl.spillLoc == sym1))
525 /*-----------------------------------------------------------------*/
526 /* sameRegs - two asmops have the same registers */
527 /*-----------------------------------------------------------------*/
529 sameRegs (asmop * aop1, asmop * aop2)
536 if (aop1->type != AOP_REG ||
537 aop2->type != AOP_REG)
540 if (aop1->size != aop2->size)
543 for (i = 0; i < aop1->size; i++)
544 if (aop1->aopu.aop_reg[i] !=
545 aop2->aopu.aop_reg[i])
551 /*-----------------------------------------------------------------*/
552 /* aopOp - allocates an asmop for an operand : */
553 /*-----------------------------------------------------------------*/
555 aopOp (operand * op, iCode * ic, bool result)
564 /* if this a literal */
565 if (IS_OP_LITERAL (op))
567 op->aop = aop = newAsmop (AOP_LIT);
568 aop->aopu.aop_lit = op->operand.valOperand;
569 aop->size = getSize (operandType (op));
573 /* if already has a asmop then continue */
577 /* if the underlying symbol has a aop */
578 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
580 op->aop = OP_SYMBOL (op)->aop;
584 /* if this is a true symbol */
585 if (IS_TRUE_SYMOP (op))
587 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
591 /* this is a temporary : this has
597 e) can be a return use only */
599 sym = OP_SYMBOL (op);
601 /* if the type is a conditional */
602 if (sym->regType == REG_CND)
604 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
609 /* if it is spilt then two situations
611 b) has a spill location */
612 if (sym->isspilt || sym->nRegs == 0)
615 /* rematerialize it NOW */
618 sym->aop = op->aop = aop =
620 aop->size = getSize (sym->type);
627 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
628 aop->size = getSize (sym->type);
629 for (i = 0; i < 2; i++)
630 aop->aopu.aop_str[i] = accUse[i];
638 aop = op->aop = sym->aop = newAsmop (AOP_STR);
639 aop->size = getSize (sym->type);
640 for (i = 0; i < fReturnSizeMCS51; i++)
641 aop->aopu.aop_str[i] = fReturn[i];
645 /* else spill location */
646 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
647 /* force a new aop if sizes differ */
648 sym->usl.spillLoc->aop = NULL;
650 sym->aop = op->aop = aop =
651 aopForSym (ic, sym->usl.spillLoc, result);
652 aop->size = getSize (sym->type);
656 /* must be in a register */
657 sym->aop = op->aop = aop = newAsmop (AOP_REG);
658 aop->size = sym->nRegs;
659 for (i = 0; i < sym->nRegs; i++)
660 aop->aopu.aop_reg[i] = sym->regs[i];
663 /*-----------------------------------------------------------------*/
664 /* freeAsmop - free up the asmop given to an operand */
665 /*----------------------------------------------------------------*/
667 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
684 /* depending on the asmop type only three cases need work AOP_RO
685 , AOP_R1 && AOP_STK */
693 emitcode ("pop", "ar0");
697 bitVectUnSetBit (ic->rUsed, R0_IDX);
705 emitcode ("pop", "ar1");
709 bitVectUnSetBit (ic->rUsed, R1_IDX);
715 int stk = aop->aopu.aop_stk + aop->size;
716 bitVectUnSetBit (ic->rUsed, R0_IDX);
717 bitVectUnSetBit (ic->rUsed, R1_IDX);
719 getFreePtr (ic, &aop, FALSE);
723 emitcode ("mov", "a,_bp");
724 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
725 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
729 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
734 emitcode ("pop", "acc");
735 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
738 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
741 freeAsmop (op, NULL, ic, TRUE);
744 emitcode ("pop", "ar0");
750 emitcode ("pop", "ar1");
757 /* all other cases just dealloc */
763 OP_SYMBOL (op)->aop = NULL;
764 /* if the symbol has a spill */
766 SPIL_LOC (op)->aop = NULL;
771 /*-----------------------------------------------------------------*/
772 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
773 /* clobber the accumulator */
774 /*-----------------------------------------------------------------*/
776 aopGetUsesAcc (asmop *aop, int offset)
778 if (offset > (aop->size - 1))
796 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
805 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
809 /* Error case --- will have been caught already */
816 /*-----------------------------------------------------------------*/
817 /* aopGet - for fetching value of the aop */
818 /*-----------------------------------------------------------------*/
820 aopGet (asmop * aop, int offset, bool bit16, bool dname)
825 /* offset is greater than
827 if (offset > (aop->size - 1) &&
828 aop->type != AOP_LIT)
831 /* depending on type */
837 /* if we need to increment it */
838 while (offset > aop->coff)
840 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
844 while (offset < aop->coff)
846 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
853 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
854 return (dname ? "acc" : "a");
856 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
857 rs = Safe_calloc (1, strlen (s) + 1);
862 if (aop->code && aop->coff==0 && offset>=1) {
863 emitcode ("mov", "a,#0x%02x", offset);
864 emitcode ("movc", "a,@a+dptr");
865 return (dname ? "acc" : "a");
868 while (offset > aop->coff)
870 emitcode ("inc", "dptr");
874 while (offset < aop->coff)
876 emitcode ("lcall", "__decdptr");
883 emitcode ("clr", "a");
884 emitcode ("movc", "a,@a+dptr");
888 emitcode ("movx", "a,@dptr");
890 return (dname ? "acc" : "a");
894 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
895 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
897 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
899 sprintf (s, "#(%s >> %d)",
900 aop->aopu.aop_immd.aop_immd1,
904 aop->aopu.aop_immd.aop_immd1);
905 rs = Safe_calloc (1, strlen (s) + 1);
911 sprintf (s, "(%s + %d)",
915 sprintf (s, "%s", aop->aopu.aop_dir);
916 rs = Safe_calloc (1, strlen (s) + 1);
922 return aop->aopu.aop_reg[offset]->dname;
924 return aop->aopu.aop_reg[offset]->name;
927 emitcode ("clr", "a");
928 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
929 emitcode ("rlc", "a");
930 return (dname ? "acc" : "a");
933 if (!offset && dname)
935 return aop->aopu.aop_str[offset];
938 return aopLiteral (aop->aopu.aop_lit, offset);
942 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
946 return aop->aopu.aop_str[offset];
950 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
951 "aopget got unsupported aop->type");
954 /*-----------------------------------------------------------------*/
955 /* aopPut - puts a string for a aop */
956 /*-----------------------------------------------------------------*/
958 aopPut (asmop * aop, char *s, int offset)
962 if (aop->size && offset > (aop->size - 1))
964 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
965 "aopPut got offset > aop->size");
969 /* will assign value to value */
970 /* depending on where it is ofcourse */
975 sprintf (d, "(%s + %d)",
976 aop->aopu.aop_dir, offset);
978 sprintf (d, "%s", aop->aopu.aop_dir);
981 emitcode ("mov", "%s,%s", d, s);
986 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
987 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
990 strcmp (s, "r0") == 0 ||
991 strcmp (s, "r1") == 0 ||
992 strcmp (s, "r2") == 0 ||
993 strcmp (s, "r3") == 0 ||
994 strcmp (s, "r4") == 0 ||
995 strcmp (s, "r5") == 0 ||
996 strcmp (s, "r6") == 0 ||
997 strcmp (s, "r7") == 0)
998 emitcode ("mov", "%s,%s",
999 aop->aopu.aop_reg[offset]->dname, s);
1001 emitcode ("mov", "%s,%s",
1002 aop->aopu.aop_reg[offset]->name, s);
1009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1010 "aopPut writting to code space");
1014 while (offset > aop->coff)
1017 emitcode ("inc", "dptr");
1020 while (offset < aop->coff)
1023 emitcode ("lcall", "__decdptr");
1028 /* if not in accumulater */
1031 emitcode ("movx", "@dptr,a");
1036 while (offset > aop->coff)
1039 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1041 while (offset < aop->coff)
1044 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1051 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1057 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1059 else if (strcmp (s, "r0") == 0 ||
1060 strcmp (s, "r1") == 0 ||
1061 strcmp (s, "r2") == 0 ||
1062 strcmp (s, "r3") == 0 ||
1063 strcmp (s, "r4") == 0 ||
1064 strcmp (s, "r5") == 0 ||
1065 strcmp (s, "r6") == 0 ||
1066 strcmp (s, "r7") == 0)
1069 sprintf (buffer, "a%s", s);
1070 emitcode ("mov", "@%s,%s",
1071 aop->aopu.aop_ptr->name, buffer);
1074 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1079 if (strcmp (s, "a") == 0)
1080 emitcode ("push", "acc");
1084 emitcode ("push", "acc");
1086 emitcode ("push", s);
1092 /* if bit variable */
1093 if (!aop->aopu.aop_dir)
1095 emitcode ("clr", "a");
1096 emitcode ("rlc", "a");
1101 emitcode ("clr", "%s", aop->aopu.aop_dir);
1103 emitcode ("setb", "%s", aop->aopu.aop_dir);
1104 else if (!strcmp (s, "c"))
1105 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1108 if (strcmp (s, "a"))
1113 /* set C, if a >= 1 */
1114 emitcode ("add", "a,#0xff");
1115 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1123 if (strcmp (aop->aopu.aop_str[offset], s))
1124 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1129 if (!offset && (strcmp (s, "acc") == 0))
1132 if (strcmp (aop->aopu.aop_str[offset], s))
1133 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1137 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1138 "aopPut got unsupported aop->type");
1146 /*-----------------------------------------------------------------*/
1147 /* pointToEnd :- points to the last byte of the operand */
1148 /*-----------------------------------------------------------------*/
1150 pointToEnd (asmop * aop)
1156 aop->coff = count = (aop->size - 1);
1162 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1166 emitcode ("inc", "dptr");
1173 /*-----------------------------------------------------------------*/
1174 /* reAdjustPreg - points a register back to where it should */
1175 /*-----------------------------------------------------------------*/
1177 reAdjustPreg (asmop * aop)
1179 if ((aop->coff==0) || aop->size <= 1)
1187 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1192 emitcode ("lcall", "__decdptr");
1199 #define AOP(op) op->aop
1200 #define AOP_TYPE(op) AOP(op)->type
1201 #define AOP_SIZE(op) AOP(op)->size
1202 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1203 AOP_TYPE(x) == AOP_R0))
1205 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1206 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1208 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1209 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1210 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1212 /*-----------------------------------------------------------------*/
1213 /* genNotFloat - generates not for float operations */
1214 /*-----------------------------------------------------------------*/
1216 genNotFloat (operand * op, operand * res)
1222 D(emitcode ("; genNotFloat",""));
1224 /* we will put 127 in the first byte of
1226 aopPut (AOP (res), "#127", 0);
1227 size = AOP_SIZE (op) - 1;
1230 l = aopGet (op->aop, offset++, FALSE, FALSE);
1235 emitcode ("orl", "a,%s",
1237 offset++, FALSE, FALSE));
1240 tlbl = newiTempLabel (NULL);
1241 aopPut (res->aop, one, 1);
1242 emitcode ("jz", "%05d$", (tlbl->key + 100));
1243 aopPut (res->aop, zero, 1);
1244 emitcode ("", "%05d$:", (tlbl->key + 100));
1246 size = res->aop->size - 2;
1248 /* put zeros in the rest */
1250 aopPut (res->aop, zero, offset++);
1253 /*-----------------------------------------------------------------*/
1254 /* opIsGptr: returns non-zero if the passed operand is */
1255 /* a generic pointer type. */
1256 /*-----------------------------------------------------------------*/
1258 opIsGptr (operand * op)
1260 sym_link *type = operandType (op);
1262 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1269 /*-----------------------------------------------------------------*/
1270 /* getDataSize - get the operand data size */
1271 /*-----------------------------------------------------------------*/
1273 getDataSize (operand * op)
1276 size = AOP_SIZE (op);
1277 if (size == GPTRSIZE)
1279 sym_link *type = operandType (op);
1280 if (IS_GENPTR (type))
1282 /* generic pointer; arithmetic operations
1283 * should ignore the high byte (pointer type).
1291 /*-----------------------------------------------------------------*/
1292 /* outAcc - output Acc */
1293 /*-----------------------------------------------------------------*/
1295 outAcc (operand * result)
1298 size = getDataSize (result);
1301 aopPut (AOP (result), "a", 0);
1304 /* unsigned or positive */
1307 aopPut (AOP (result), zero, offset++);
1312 /*-----------------------------------------------------------------*/
1313 /* outBitC - output a bit C */
1314 /*-----------------------------------------------------------------*/
1316 outBitC (operand * result)
1318 /* if the result is bit */
1319 if (AOP_TYPE (result) == AOP_CRY)
1320 aopPut (AOP (result), "c", 0);
1323 emitcode ("clr", "a");
1324 emitcode ("rlc", "a");
1329 /*-----------------------------------------------------------------*/
1330 /* toBoolean - emit code for orl a,operator(sizeop) */
1331 /*-----------------------------------------------------------------*/
1333 toBoolean (operand * oper)
1335 int size = AOP_SIZE (oper) - 1;
1337 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1339 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1343 /*-----------------------------------------------------------------*/
1344 /* genNot - generate code for ! operation */
1345 /*-----------------------------------------------------------------*/
1350 sym_link *optype = operandType (IC_LEFT (ic));
1352 D(emitcode ("; genNot",""));
1354 /* assign asmOps to operand & result */
1355 aopOp (IC_LEFT (ic), ic, FALSE);
1356 aopOp (IC_RESULT (ic), ic, TRUE);
1358 /* if in bit space then a special case */
1359 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1361 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1362 emitcode ("cpl", "c");
1363 outBitC (IC_RESULT (ic));
1367 /* if type float then do float */
1368 if (IS_FLOAT (optype))
1370 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1374 toBoolean (IC_LEFT (ic));
1376 tlbl = newiTempLabel (NULL);
1377 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1378 emitcode ("", "%05d$:", tlbl->key + 100);
1379 outBitC (IC_RESULT (ic));
1382 /* release the aops */
1383 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1384 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1388 /*-----------------------------------------------------------------*/
1389 /* genCpl - generate code for complement */
1390 /*-----------------------------------------------------------------*/
1398 D(emitcode ("; genCpl",""));
1400 /* assign asmOps to operand & result */
1401 aopOp (IC_LEFT (ic), ic, FALSE);
1402 aopOp (IC_RESULT (ic), ic, TRUE);
1404 /* special case if in bit space */
1405 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1406 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1407 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1408 emitcode ("cpl", "c");
1409 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1412 tlbl=newiTempLabel(NULL);
1413 emitcode ("cjne", "%s,#0x01,%05d$",
1414 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1415 emitcode ("", "%05d$:", tlbl->key+100);
1416 outBitC (IC_RESULT(ic));
1420 size = AOP_SIZE (IC_RESULT (ic));
1423 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1425 emitcode ("cpl", "a");
1426 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1431 /* release the aops */
1432 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* genUminusFloat - unary minus for floating points */
1438 /*-----------------------------------------------------------------*/
1440 genUminusFloat (operand * op, operand * result)
1442 int size, offset = 0;
1445 D(emitcode ("; genUminusFloat",""));
1447 /* for this we just copy and then flip the bit */
1449 size = AOP_SIZE (op) - 1;
1453 aopPut (AOP (result),
1454 aopGet (AOP (op), offset, FALSE, FALSE),
1459 l = aopGet (AOP (op), offset, FALSE, FALSE);
1463 emitcode ("cpl", "acc.7");
1464 aopPut (AOP (result), "a", offset);
1467 /*-----------------------------------------------------------------*/
1468 /* genUminus - unary minus code generation */
1469 /*-----------------------------------------------------------------*/
1471 genUminus (iCode * ic)
1474 sym_link *optype, *rtype;
1477 D(emitcode ("; genUminus",""));
1480 aopOp (IC_LEFT (ic), ic, FALSE);
1481 aopOp (IC_RESULT (ic), ic, TRUE);
1483 /* if both in bit space then special
1485 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1486 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1489 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1490 emitcode ("cpl", "c");
1491 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1495 optype = operandType (IC_LEFT (ic));
1496 rtype = operandType (IC_RESULT (ic));
1498 /* if float then do float stuff */
1499 if (IS_FLOAT (optype))
1501 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1505 /* otherwise subtract from zero */
1506 size = AOP_SIZE (IC_LEFT (ic));
1511 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1512 if (!strcmp (l, "a"))
1516 emitcode ("cpl", "a");
1517 emitcode ("addc", "a,#0");
1523 emitcode ("clr", "a");
1524 emitcode ("subb", "a,%s", l);
1526 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1529 /* if any remaining bytes in the result */
1530 /* we just need to propagate the sign */
1531 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1533 emitcode ("rlc", "a");
1534 emitcode ("subb", "a,acc");
1536 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1540 /* release the aops */
1541 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* saveRegisters - will look for a call and save the registers */
1547 /*-----------------------------------------------------------------*/
1549 saveRegisters (iCode * lic)
1556 for (ic = lic; ic; ic = ic->next)
1557 if (ic->op == CALL || ic->op == PCALL)
1562 fprintf (stderr, "found parameter push with no function call\n");
1566 /* if the registers have been saved already or don't need to be then
1568 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1569 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1572 /* safe the registers in use at this time but skip the
1573 ones for the result */
1574 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1575 mcs51_rUmaskForOp (IC_RESULT(ic)));
1578 if (options.useXstack)
1580 if (bitVectBitValue (rsave, R0_IDX))
1581 emitcode ("mov", "b,r0");
1582 emitcode ("mov", "r0,%s", spname);
1583 for (i = 0; i < mcs51_nRegs; i++)
1585 if (bitVectBitValue (rsave, i))
1588 emitcode ("mov", "a,b");
1590 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1591 emitcode ("movx", "@r0,a");
1592 emitcode ("inc", "r0");
1595 emitcode ("mov", "%s,r0", spname);
1596 if (bitVectBitValue (rsave, R0_IDX))
1597 emitcode ("mov", "r0,b");
1600 for (i = 0; i < mcs51_nRegs; i++)
1602 if (bitVectBitValue (rsave, i))
1603 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1607 /*-----------------------------------------------------------------*/
1608 /* unsaveRegisters - pop the pushed registers */
1609 /*-----------------------------------------------------------------*/
1611 unsaveRegisters (iCode * ic)
1616 /* restore the registers in use at this time but skip the
1617 ones for the result */
1618 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1619 mcs51_rUmaskForOp (IC_RESULT(ic)));
1621 if (options.useXstack)
1623 emitcode ("mov", "r0,%s", spname);
1624 for (i = mcs51_nRegs; i >= 0; i--)
1626 if (bitVectBitValue (rsave, i))
1628 emitcode ("dec", "r0");
1629 emitcode ("movx", "a,@r0");
1631 emitcode ("mov", "b,a");
1633 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1637 emitcode ("mov", "%s,r0", spname);
1638 if (bitVectBitValue (rsave, R0_IDX))
1639 emitcode ("mov", "r0,b");
1642 for (i = mcs51_nRegs; i >= 0; i--)
1644 if (bitVectBitValue (rsave, i))
1645 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1651 /*-----------------------------------------------------------------*/
1653 /*-----------------------------------------------------------------*/
1655 pushSide (operand * oper, int size)
1660 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1661 if (AOP_TYPE (oper) != AOP_REG &&
1662 AOP_TYPE (oper) != AOP_DIR &&
1665 emitcode ("mov", "a,%s", l);
1666 emitcode ("push", "acc");
1669 emitcode ("push", "%s", l);
1673 /*-----------------------------------------------------------------*/
1674 /* assignResultValue - */
1675 /*-----------------------------------------------------------------*/
1677 assignResultValue (operand * oper)
1680 int size = AOP_SIZE (oper);
1683 aopPut (AOP (oper), fReturn[offset], offset);
1689 /*-----------------------------------------------------------------*/
1690 /* genXpush - pushes onto the external stack */
1691 /*-----------------------------------------------------------------*/
1693 genXpush (iCode * ic)
1695 asmop *aop = newAsmop (0);
1697 int size, offset = 0;
1699 D(emitcode ("; genXpush",""));
1701 aopOp (IC_LEFT (ic), ic, FALSE);
1702 r = getFreePtr (ic, &aop, FALSE);
1705 emitcode ("mov", "%s,_spx", r->name);
1707 size = AOP_SIZE (IC_LEFT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)),
1712 offset++, FALSE, FALSE);
1714 emitcode ("movx", "@%s,a", r->name);
1715 emitcode ("inc", "%s", r->name);
1720 emitcode ("mov", "_spx,%s", r->name);
1722 freeAsmop (NULL, aop, ic, TRUE);
1723 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* genIpush - genrate code for pushing this gets a little complex */
1728 /*-----------------------------------------------------------------*/
1730 genIpush (iCode * ic)
1732 int size, offset = 0;
1735 D(emitcode ("; genIpush",""));
1737 /* if this is not a parm push : ie. it is spill push
1738 and spill push is always done on the local stack */
1742 /* and the item is spilt then do nothing */
1743 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1746 aopOp (IC_LEFT (ic), ic, FALSE);
1747 size = AOP_SIZE (IC_LEFT (ic));
1748 /* push it on the stack */
1751 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1757 emitcode ("push", "%s", l);
1762 /* this is a paramter push: in this case we call
1763 the routine to find the call and save those
1764 registers that need to be saved */
1767 /* if use external stack then call the external
1768 stack pushing routine */
1769 if (options.useXstack)
1775 /* then do the push */
1776 aopOp (IC_LEFT (ic), ic, FALSE);
1779 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1780 size = AOP_SIZE (IC_LEFT (ic));
1784 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1785 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1786 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1789 emitcode ("mov", "a,%s", l);
1790 emitcode ("push", "acc");
1793 emitcode ("push", "%s", l);
1796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1799 /*-----------------------------------------------------------------*/
1800 /* genIpop - recover the registers: can happen only for spilling */
1801 /*-----------------------------------------------------------------*/
1803 genIpop (iCode * ic)
1807 D(emitcode ("; genIpop",""));
1809 /* if the temp was not pushed then */
1810 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1813 aopOp (IC_LEFT (ic), ic, FALSE);
1814 size = AOP_SIZE (IC_LEFT (ic));
1815 offset = (size - 1);
1817 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1820 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1823 /*-----------------------------------------------------------------*/
1824 /* unsaveRBank - restores the resgister bank from stack */
1825 /*-----------------------------------------------------------------*/
1827 unsaveRBank (int bank, iCode * ic, bool popPsw)
1833 if (options.useXstack)
1837 /* Assume r0 is available for use. */
1838 r = mcs51_regWithIdx (R0_IDX);;
1843 r = getFreePtr (ic, &aop, FALSE);
1845 emitcode ("mov", "%s,_spx", r->name);
1850 if (options.useXstack)
1852 emitcode ("movx", "a,@%s", r->name);
1853 emitcode ("mov", "psw,a");
1854 emitcode ("dec", "%s", r->name);
1858 emitcode ("pop", "psw");
1862 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1864 if (options.useXstack)
1866 emitcode ("movx", "a,@%s", r->name);
1867 emitcode ("mov", "(%s+%d),a",
1868 regs8051[i].base, 8 * bank + regs8051[i].offset);
1869 emitcode ("dec", "%s", r->name);
1873 emitcode ("pop", "(%s+%d)",
1874 regs8051[i].base, 8 * bank + regs8051[i].offset);
1877 if (options.useXstack)
1879 emitcode ("mov", "_spx,%s", r->name);
1884 freeAsmop (NULL, aop, ic, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* saveRBank - saves an entire register bank on the stack */
1890 /*-----------------------------------------------------------------*/
1892 saveRBank (int bank, iCode * ic, bool pushPsw)
1898 if (options.useXstack)
1902 /* Assume r0 is available for use. */
1903 r = mcs51_regWithIdx (R0_IDX);;
1908 r = getFreePtr (ic, &aop, FALSE);
1910 emitcode ("mov", "%s,_spx", r->name);
1913 for (i = 0; i < mcs51_nRegs; i++)
1915 if (options.useXstack)
1917 emitcode ("inc", "%s", r->name);
1918 emitcode ("mov", "a,(%s+%d)",
1919 regs8051[i].base, 8 * bank + regs8051[i].offset);
1920 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("push", "(%s+%d)",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1929 if (options.useXstack)
1931 emitcode ("mov", "a,psw");
1932 emitcode ("movx", "@%s,a", r->name);
1933 emitcode ("inc", "%s", r->name);
1934 emitcode ("mov", "_spx,%s", r->name);
1939 emitcode ("push", "psw");
1942 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1947 freeAsmop (NULL, aop, ic, TRUE);
1956 /*-----------------------------------------------------------------*/
1957 /* genSend - gen code for SEND */
1958 /*-----------------------------------------------------------------*/
1959 static void genSend(set *sendSet)
1964 for (sic = setFirstItem (_G.sendSet); sic;
1965 sic = setNextItem (_G.sendSet)) {
1966 int size, offset = 0;
1967 aopOp (IC_LEFT (sic), sic, FALSE);
1968 size = AOP_SIZE (IC_LEFT (sic));
1970 if (sic->argreg == 1) {
1972 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1974 if (strcmp (l, fReturn[offset]))
1975 emitcode ("mov", "%s,%s", fReturn[offset], l);
1981 emitcode ("mov","b1_%d,%s",rb1_count++,
1982 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1985 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1989 /*-----------------------------------------------------------------*/
1990 /* genCall - generates a call statement */
1991 /*-----------------------------------------------------------------*/
1993 genCall (iCode * ic)
1996 // bool restoreBank = FALSE;
1997 bool swapBanks = FALSE;
1999 D(emitcode("; genCall",""));
2001 dtype = operandType (IC_LEFT (ic));
2002 /* if send set is not empty the assign */
2005 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2006 genSend(reverseSet(_G.sendSet));
2008 genSend(_G.sendSet);
2014 /* if we are calling a not _naked function that is not using
2015 the same register bank then we need to save the
2016 destination registers on the stack */
2017 dtype = operandType (IC_LEFT (ic));
2018 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2019 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2020 !IFFUNC_ISISR (dtype))
2025 /* if caller saves & we have not saved then */
2031 emitcode ("mov", "psw,#0x%02x",
2032 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2036 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2037 OP_SYMBOL (IC_LEFT (ic))->rname :
2038 OP_SYMBOL (IC_LEFT (ic))->name));
2042 emitcode ("mov", "psw,#0x%02x",
2043 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2046 /* if we need assign a result value */
2047 if ((IS_ITEMP (IC_RESULT (ic)) &&
2048 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2049 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2050 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2051 IS_TRUE_SYMOP (IC_RESULT (ic)))
2055 aopOp (IC_RESULT (ic), ic, FALSE);
2058 assignResultValue (IC_RESULT (ic));
2060 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2063 /* adjust the stack for parameters if
2068 if (ic->parmBytes > 3)
2070 emitcode ("mov", "a,%s", spname);
2071 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2072 emitcode ("mov", "%s,a", spname);
2075 for (i = 0; i < ic->parmBytes; i++)
2076 emitcode ("dec", "%s", spname);
2079 /* if we hade saved some registers then unsave them */
2080 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2081 unsaveRegisters (ic);
2083 // /* if register bank was saved then pop them */
2085 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2088 /*-----------------------------------------------------------------*/
2089 /* -10l - generates a call by pointer statement */
2090 /*-----------------------------------------------------------------*/
2092 genPcall (iCode * ic)
2095 symbol *rlbl = newiTempLabel (NULL);
2096 // bool restoreBank=FALSE;
2097 bool swapBanks = FALSE;
2099 D(emitcode("; genPCall",""));
2101 /* if caller saves & we have not saved then */
2105 /* if we are calling a not _naked function that is not using
2106 the same register bank then we need to save the
2107 destination registers on the stack */
2108 dtype = operandType (IC_LEFT (ic))->next;
2109 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2110 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2111 !IFFUNC_ISISR (dtype))
2113 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2114 // restoreBank=TRUE;
2116 // need caution message to user here
2119 /* push the return address on to the stack */
2120 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2121 emitcode ("push", "acc");
2122 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2123 emitcode ("push", "acc");
2125 /* now push the calling address */
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2128 pushSide (IC_LEFT (ic), FPTRSIZE);
2130 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2132 /* if send set is not empty the assign */
2135 genSend(reverseSet(_G.sendSet));
2141 emitcode ("mov", "psw,#0x%02x",
2142 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2146 emitcode ("ret", "");
2147 emitcode ("", "%05d$:", (rlbl->key + 100));
2152 emitcode ("mov", "psw,#0x%02x",
2153 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2156 /* if we need assign a result value */
2157 if ((IS_ITEMP (IC_RESULT (ic)) &&
2158 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2159 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2160 IS_TRUE_SYMOP (IC_RESULT (ic)))
2164 aopOp (IC_RESULT (ic), ic, FALSE);
2167 assignResultValue (IC_RESULT (ic));
2169 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2172 /* adjust the stack for parameters if
2177 if (ic->parmBytes > 3)
2179 emitcode ("mov", "a,%s", spname);
2180 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2181 emitcode ("mov", "%s,a", spname);
2184 for (i = 0; i < ic->parmBytes; i++)
2185 emitcode ("dec", "%s", spname);
2189 // /* if register bank was saved then unsave them */
2191 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2193 /* if we hade saved some registers then
2195 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2196 unsaveRegisters (ic);
2199 /*-----------------------------------------------------------------*/
2200 /* resultRemat - result is rematerializable */
2201 /*-----------------------------------------------------------------*/
2203 resultRemat (iCode * ic)
2205 if (SKIP_IC (ic) || ic->op == IFX)
2208 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2210 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2211 if (sym->remat && !POINTER_SET (ic))
2218 #if defined(__BORLANDC__) || defined(_MSC_VER)
2219 #define STRCASECMP stricmp
2221 #define STRCASECMP strcasecmp
2224 /*-----------------------------------------------------------------*/
2225 /* inExcludeList - return 1 if the string is in exclude Reg list */
2226 /*-----------------------------------------------------------------*/
2228 inExcludeList (char *s)
2232 if (options.excludeRegs[i] &&
2233 STRCASECMP (options.excludeRegs[i], "none") == 0)
2236 for (i = 0; options.excludeRegs[i]; i++)
2238 if (options.excludeRegs[i] &&
2239 STRCASECMP (s, options.excludeRegs[i]) == 0)
2245 /*-----------------------------------------------------------------*/
2246 /* genFunction - generated code for function entry */
2247 /*-----------------------------------------------------------------*/
2249 genFunction (iCode * ic)
2253 bool switchedPSW = FALSE;
2254 int calleesaves_saved_register = -1;
2257 /* create the function header */
2258 emitcode (";", "-----------------------------------------");
2259 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2260 emitcode (";", "-----------------------------------------");
2262 emitcode ("", "%s:", sym->rname);
2263 ftype = operandType (IC_LEFT (ic));
2265 if (IFFUNC_ISNAKED(ftype))
2267 emitcode(";", "naked function: no prologue.");
2271 /* if critical function then turn interrupts off */
2272 if (IFFUNC_ISCRITICAL (ftype))
2273 emitcode ("clr", "ea");
2275 /* here we need to generate the equates for the
2276 register bank if required */
2277 if (FUNC_REGBANK (ftype) != rbank)
2281 rbank = FUNC_REGBANK (ftype);
2282 for (i = 0; i < mcs51_nRegs; i++)
2284 if (strcmp (regs8051[i].base, "0") == 0)
2285 emitcode ("", "%s = 0x%02x",
2287 8 * rbank + regs8051[i].offset);
2289 emitcode ("", "%s = %s + 0x%02x",
2292 8 * rbank + regs8051[i].offset);
2296 /* if this is an interrupt service routine then
2297 save acc, b, dpl, dph */
2298 if (IFFUNC_ISISR (sym->type))
2301 if (!inExcludeList ("acc"))
2302 emitcode ("push", "acc");
2303 if (!inExcludeList ("b"))
2304 emitcode ("push", "b");
2305 if (!inExcludeList ("dpl"))
2306 emitcode ("push", "dpl");
2307 if (!inExcludeList ("dph"))
2308 emitcode ("push", "dph");
2309 /* if this isr has no bank i.e. is going to
2310 run with bank 0 , then we need to save more
2312 if (!FUNC_REGBANK (sym->type))
2315 /* if this function does not call any other
2316 function then we can be economical and
2317 save only those registers that are used */
2318 if (!IFFUNC_HASFCALL(sym->type))
2322 /* if any registers used */
2325 /* save the registers used */
2326 for (i = 0; i < sym->regsUsed->size; i++)
2328 if (bitVectBitValue (sym->regsUsed, i) ||
2329 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2330 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2338 /* this function has a function call cannot
2339 determines register usage so we will have to push the
2341 saveRBank (0, ic, FALSE);
2342 if (options.parms_in_bank1) {
2344 for (i=0; i < 8 ; i++ ) {
2345 emitcode ("push","%s",rb1regs[i]);
2352 /* This ISR uses a non-zero bank.
2354 * We assume that the bank is available for our
2357 * However, if this ISR calls a function which uses some
2358 * other bank, we must save that bank entirely.
2360 unsigned long banksToSave = 0;
2362 if (IFFUNC_HASFCALL(sym->type))
2365 #define MAX_REGISTER_BANKS 4
2370 for (i = ic; i; i = i->next)
2372 if (i->op == ENDFUNCTION)
2374 /* we got to the end OK. */
2382 dtype = operandType (IC_LEFT(i));
2384 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2386 /* Mark this bank for saving. */
2387 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2389 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2393 banksToSave |= (1 << FUNC_REGBANK(dtype));
2396 /* And note that we don't need to do it in
2404 /* This is a mess; we have no idea what
2405 * register bank the called function might
2408 * The only thing I can think of to do is
2409 * throw a warning and hope.
2411 werror(W_FUNCPTR_IN_USING_ISR);
2415 if (banksToSave && options.useXstack)
2417 /* Since we aren't passing it an ic,
2418 * saveRBank will assume r0 is available to abuse.
2420 * So switch to our (trashable) bank now, so
2421 * the caller's R0 isn't trashed.
2423 emitcode ("push", "psw");
2424 emitcode ("mov", "psw,#0x%02x",
2425 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2429 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2431 if (banksToSave & (1 << ix))
2433 saveRBank(ix, NULL, FALSE);
2437 // jwk: this needs a closer look
2438 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2443 /* if callee-save to be used for this function
2444 then save the registers being used in this function */
2445 if (IFFUNC_CALLEESAVES(sym->type))
2449 /* if any registers used */
2452 /* save the registers used */
2453 for (i = 0; i < sym->regsUsed->size; i++)
2455 if (bitVectBitValue (sym->regsUsed, i) ||
2456 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2458 /* remember one saved register for later usage */
2459 if (calleesaves_saved_register < 0)
2460 calleesaves_saved_register = i;
2461 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2469 /* set the register bank to the desired value */
2470 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2473 emitcode ("push", "psw");
2474 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2477 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2480 if (options.useXstack)
2482 emitcode ("mov", "r0,%s", spname);
2483 emitcode ("mov", "a,_bp");
2484 emitcode ("movx", "@r0,a");
2485 emitcode ("inc", "%s", spname);
2489 /* set up the stack */
2490 emitcode ("push", "_bp"); /* save the callers stack */
2492 emitcode ("mov", "_bp,%s", spname);
2495 /* adjust the stack for the function */
2501 werror (W_STACK_OVERFLOW, sym->name);
2503 if (i > 3 && sym->recvSize < 4)
2506 emitcode ("mov", "a,sp");
2507 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2508 emitcode ("mov", "sp,a");
2513 if (IFFUNC_CALLEESAVES(sym->type))
2515 /* if it's a callee-saves function we need a saved register */
2516 if (calleesaves_saved_register >= 0)
2518 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2519 emitcode ("mov", "a,sp");
2520 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2521 emitcode ("mov", "sp,a");
2522 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2525 /* do it the hard way */
2527 emitcode ("inc", "sp");
2531 /* not callee-saves, we can clobber r0 */
2532 emitcode ("mov", "r0,a");
2533 emitcode ("mov", "a,sp");
2534 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2535 emitcode ("mov", "sp,a");
2536 emitcode ("mov", "a,r0");
2541 emitcode ("inc", "sp");
2547 emitcode ("mov", "a,_spx");
2548 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2549 emitcode ("mov", "_spx,a");
2554 /*-----------------------------------------------------------------*/
2555 /* genEndFunction - generates epilogue for functions */
2556 /*-----------------------------------------------------------------*/
2558 genEndFunction (iCode * ic)
2560 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2562 if (IFFUNC_ISNAKED(sym->type))
2564 emitcode(";", "naked function: no epilogue.");
2568 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2570 emitcode ("mov", "%s,_bp", spname);
2573 /* if use external stack but some variables were
2574 added to the local stack then decrement the
2576 if (options.useXstack && sym->stack)
2578 emitcode ("mov", "a,sp");
2579 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2580 emitcode ("mov", "sp,a");
2584 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2586 if (options.useXstack)
2588 emitcode ("mov", "r0,%s", spname);
2589 emitcode ("movx", "a,@r0");
2590 emitcode ("mov", "_bp,a");
2591 emitcode ("dec", "%s", spname);
2595 emitcode ("pop", "_bp");
2599 /* restore the register bank */
2600 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2602 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2603 || !options.useXstack)
2605 /* Special case of ISR using non-zero bank with useXstack
2608 emitcode ("pop", "psw");
2612 if (IFFUNC_ISISR (sym->type))
2615 /* now we need to restore the registers */
2616 /* if this isr has no bank i.e. is going to
2617 run with bank 0 , then we need to save more
2619 if (!FUNC_REGBANK (sym->type))
2621 /* if this function does not call any other
2622 function then we can be economical and
2623 save only those registers that are used */
2624 if (!IFFUNC_HASFCALL(sym->type))
2628 /* if any registers used */
2631 /* save the registers used */
2632 for (i = sym->regsUsed->size; i >= 0; i--)
2634 if (bitVectBitValue (sym->regsUsed, i) ||
2635 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2636 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2643 if (options.parms_in_bank1) {
2645 for (i = 7 ; i >= 0 ; i-- ) {
2646 emitcode ("pop","%s",rb1regs[i]);
2649 /* this function has a function call cannot
2650 determines register usage so we will have to pop the
2652 unsaveRBank (0, ic, FALSE);
2657 /* This ISR uses a non-zero bank.
2659 * Restore any register banks saved by genFunction
2662 // jwk: this needs a closer look
2663 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2666 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2668 if (savedBanks & (1 << ix))
2670 unsaveRBank(ix, NULL, FALSE);
2674 if (options.useXstack)
2676 /* Restore bank AFTER calling unsaveRBank,
2677 * since it can trash r0.
2679 emitcode ("pop", "psw");
2683 if (!inExcludeList ("dph"))
2684 emitcode ("pop", "dph");
2685 if (!inExcludeList ("dpl"))
2686 emitcode ("pop", "dpl");
2687 if (!inExcludeList ("b"))
2688 emitcode ("pop", "b");
2689 if (!inExcludeList ("acc"))
2690 emitcode ("pop", "acc");
2692 if (IFFUNC_ISCRITICAL (sym->type))
2693 emitcode ("setb", "ea");
2695 /* if debug then send end of function */
2696 if (options.debug && currFunc)
2699 emitcode ("", "C$%s$%d$%d$%d ==.",
2700 FileBaseName (ic->filename), currFunc->lastLine,
2701 ic->level, ic->block);
2702 if (IS_STATIC (currFunc->etype))
2703 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2705 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2709 emitcode ("reti", "");
2713 if (IFFUNC_ISCRITICAL (sym->type))
2714 emitcode ("setb", "ea");
2716 if (IFFUNC_CALLEESAVES(sym->type))
2720 /* if any registers used */
2723 /* save the registers used */
2724 for (i = sym->regsUsed->size; i >= 0; i--)
2726 if (bitVectBitValue (sym->regsUsed, i) ||
2727 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2728 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2734 /* if debug then send end of function */
2735 if (options.debug && currFunc)
2738 emitcode ("", "C$%s$%d$%d$%d ==.",
2739 FileBaseName (ic->filename), currFunc->lastLine,
2740 ic->level, ic->block);
2741 if (IS_STATIC (currFunc->etype))
2742 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2744 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2748 emitcode ("ret", "");
2753 /*-----------------------------------------------------------------*/
2754 /* genRet - generate code for return statement */
2755 /*-----------------------------------------------------------------*/
2759 int size, offset = 0, pushed = 0;
2761 D(emitcode ("; genRet",""));
2763 /* if we have no return value then
2764 just generate the "ret" */
2768 /* we have something to return then
2769 move the return value into place */
2770 aopOp (IC_LEFT (ic), ic, FALSE);
2771 size = AOP_SIZE (IC_LEFT (ic));
2776 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2779 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2781 emitcode ("push", "%s", l);
2786 l = aopGet (AOP (IC_LEFT (ic)), offset,
2788 if (strcmp (fReturn[offset], l))
2789 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2798 if (strcmp (fReturn[pushed], "a"))
2799 emitcode ("pop", fReturn[pushed]);
2801 emitcode ("pop", "acc");
2804 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2807 /* generate a jump to the return label
2808 if the next is not the return statement */
2809 if (!(ic->next && ic->next->op == LABEL &&
2810 IC_LABEL (ic->next) == returnLabel))
2812 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2816 /*-----------------------------------------------------------------*/
2817 /* genLabel - generates a label */
2818 /*-----------------------------------------------------------------*/
2820 genLabel (iCode * ic)
2822 /* special case never generate */
2823 if (IC_LABEL (ic) == entryLabel)
2826 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2829 /*-----------------------------------------------------------------*/
2830 /* genGoto - generates a ljmp */
2831 /*-----------------------------------------------------------------*/
2833 genGoto (iCode * ic)
2835 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2838 /*-----------------------------------------------------------------*/
2839 /* findLabelBackwards: walks back through the iCode chain looking */
2840 /* for the given label. Returns number of iCode instructions */
2841 /* between that label and given ic. */
2842 /* Returns zero if label not found. */
2843 /*-----------------------------------------------------------------*/
2845 findLabelBackwards (iCode * ic, int key)
2854 /* If we have any pushes or pops, we cannot predict the distance.
2855 I don't like this at all, this should be dealt with in the
2857 if (ic->op == IPUSH || ic->op == IPOP) {
2861 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2870 /*-----------------------------------------------------------------*/
2871 /* genPlusIncr :- does addition with increment if possible */
2872 /*-----------------------------------------------------------------*/
2874 genPlusIncr (iCode * ic)
2876 unsigned int icount;
2877 unsigned int size = getDataSize (IC_RESULT (ic));
2879 /* will try to generate an increment */
2880 /* if the right side is not a literal
2882 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2885 /* if the literal value of the right hand side
2886 is greater than 4 then it is not worth it */
2887 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2890 D(emitcode ("; genPlusIncr",""));
2892 /* if increment 16 bits in register */
2893 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2894 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2902 /* If the next instruction is a goto and the goto target
2903 * is < 10 instructions previous to this, we can generate
2904 * jumps straight to that target.
2906 if (ic->next && ic->next->op == GOTO
2907 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2908 && labelRange <= 10)
2910 emitcode (";", "tail increment optimized");
2911 tlbl = IC_LABEL (ic->next);
2916 tlbl = newiTempLabel (NULL);
2919 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2921 IS_AOP_PREG (IC_RESULT (ic)))
2922 emitcode ("cjne", "%s,#0x00,%05d$",
2923 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2927 emitcode ("clr", "a");
2928 emitcode ("cjne", "a,%s,%05d$",
2929 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2933 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2936 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2937 IS_AOP_PREG (IC_RESULT (ic)))
2938 emitcode ("cjne", "%s,#0x00,%05d$",
2939 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2942 emitcode ("cjne", "a,%s,%05d$",
2943 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2946 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2950 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2951 IS_AOP_PREG (IC_RESULT (ic)))
2952 emitcode ("cjne", "%s,#0x00,%05d$",
2953 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2957 emitcode ("cjne", "a,%s,%05d$",
2958 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2961 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2966 emitcode ("", "%05d$:", tlbl->key + 100);
2971 /* if the sizes are greater than 1 then we cannot */
2972 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2973 AOP_SIZE (IC_LEFT (ic)) > 1)
2976 /* we can if the aops of the left & result match or
2977 if they are in registers and the registers are the
2979 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2984 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2985 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2986 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2992 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3001 /*-----------------------------------------------------------------*/
3002 /* outBitAcc - output a bit in acc */
3003 /*-----------------------------------------------------------------*/
3005 outBitAcc (operand * result)
3007 symbol *tlbl = newiTempLabel (NULL);
3008 /* if the result is a bit */
3009 if (AOP_TYPE (result) == AOP_CRY)
3011 aopPut (AOP (result), "a", 0);
3015 emitcode ("jz", "%05d$", tlbl->key + 100);
3016 emitcode ("mov", "a,%s", one);
3017 emitcode ("", "%05d$:", tlbl->key + 100);
3022 /*-----------------------------------------------------------------*/
3023 /* genPlusBits - generates code for addition of two bits */
3024 /*-----------------------------------------------------------------*/
3026 genPlusBits (iCode * ic)
3028 D(emitcode ("; genPlusBits",""));
3030 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3032 symbol *lbl = newiTempLabel (NULL);
3033 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3034 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3035 emitcode ("cpl", "c");
3036 emitcode ("", "%05d$:", (lbl->key + 100));
3037 outBitC (IC_RESULT (ic));
3041 emitcode ("clr", "a");
3042 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3043 emitcode ("rlc", "a");
3044 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3045 emitcode ("addc", "a,#0x00");
3046 outAcc (IC_RESULT (ic));
3051 /* This is the original version of this code.
3053 * This is being kept around for reference,
3054 * because I am not entirely sure I got it right...
3057 adjustArithmeticResult (iCode * ic)
3059 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3060 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3061 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3062 aopPut (AOP (IC_RESULT (ic)),
3063 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3066 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3067 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3068 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3069 aopPut (AOP (IC_RESULT (ic)),
3070 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3073 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3074 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3075 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3076 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3077 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3080 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3081 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3085 /* This is the pure and virtuous version of this code.
3086 * I'm pretty certain it's right, but not enough to toss the old
3090 adjustArithmeticResult (iCode * ic)
3092 if (opIsGptr (IC_RESULT (ic)) &&
3093 opIsGptr (IC_LEFT (ic)) &&
3094 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3096 aopPut (AOP (IC_RESULT (ic)),
3097 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3101 if (opIsGptr (IC_RESULT (ic)) &&
3102 opIsGptr (IC_RIGHT (ic)) &&
3103 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3105 aopPut (AOP (IC_RESULT (ic)),
3106 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3110 if (opIsGptr (IC_RESULT (ic)) &&
3111 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3112 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3113 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3117 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3118 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3123 /*-----------------------------------------------------------------*/
3124 /* genPlus - generates code for addition */
3125 /*-----------------------------------------------------------------*/
3127 genPlus (iCode * ic)
3129 int size, offset = 0;
3131 asmop *leftOp, *rightOp;
3133 /* special cases :- */
3135 D(emitcode ("; genPlus",""));
3137 aopOp (IC_LEFT (ic), ic, FALSE);
3138 aopOp (IC_RIGHT (ic), ic, FALSE);
3139 aopOp (IC_RESULT (ic), ic, TRUE);
3141 /* if literal, literal on the right or
3142 if left requires ACC or right is already
3144 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3145 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3146 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3148 operand *t = IC_RIGHT (ic);
3149 IC_RIGHT (ic) = IC_LEFT (ic);
3153 /* if both left & right are in bit
3155 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3156 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3162 /* if left in bit space & right literal */
3163 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3164 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3166 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3167 /* if result in bit space */
3168 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3170 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3171 emitcode ("cpl", "c");
3172 outBitC (IC_RESULT (ic));
3176 size = getDataSize (IC_RESULT (ic));
3179 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3180 emitcode ("addc", "a,#00");
3181 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3187 /* if I can do an increment instead
3188 of add then GOOD for ME */
3189 if (genPlusIncr (ic) == TRUE)
3192 size = getDataSize (IC_RESULT (ic));
3194 leftOp = AOP(IC_LEFT(ic));
3195 rightOp = AOP(IC_RIGHT(ic));
3200 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3202 emitcode("mov", "b,a");
3203 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3204 emitcode("xch", "a,b");
3205 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3206 emitcode (add, "a,b");
3208 else if (aopGetUsesAcc (leftOp, offset))
3210 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3211 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3215 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3216 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3218 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3219 add = "addc"; /* further adds must propagate carry */
3222 adjustArithmeticResult (ic);
3225 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3226 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3227 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3230 /*-----------------------------------------------------------------*/
3231 /* genMinusDec :- does subtraction with deccrement if possible */
3232 /*-----------------------------------------------------------------*/
3234 genMinusDec (iCode * ic)
3236 unsigned int icount;
3237 unsigned int size = getDataSize (IC_RESULT (ic));
3239 /* will try to generate an increment */
3240 /* if the right side is not a literal
3242 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3245 /* if the literal value of the right hand side
3246 is greater than 4 then it is not worth it */
3247 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3250 D(emitcode ("; genMinusDec",""));
3252 /* if decrement 16 bits in register */
3253 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3254 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3262 /* If the next instruction is a goto and the goto target
3263 * is <= 10 instructions previous to this, we can generate
3264 * jumps straight to that target.
3266 if (ic->next && ic->next->op == GOTO
3267 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3268 && labelRange <= 10)
3270 emitcode (";", "tail decrement optimized");
3271 tlbl = IC_LABEL (ic->next);
3276 tlbl = newiTempLabel (NULL);
3280 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3281 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3282 IS_AOP_PREG (IC_RESULT (ic)))
3283 emitcode ("cjne", "%s,#0xff,%05d$"
3284 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3288 emitcode ("mov", "a,#0xff");
3289 emitcode ("cjne", "a,%s,%05d$"
3290 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3293 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3296 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3297 IS_AOP_PREG (IC_RESULT (ic)))
3298 emitcode ("cjne", "%s,#0xff,%05d$"
3299 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3303 emitcode ("cjne", "a,%s,%05d$"
3304 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3307 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3311 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3312 IS_AOP_PREG (IC_RESULT (ic)))
3313 emitcode ("cjne", "%s,#0xff,%05d$"
3314 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3318 emitcode ("cjne", "a,%s,%05d$"
3319 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3322 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3326 emitcode ("", "%05d$:", tlbl->key + 100);
3331 /* if the sizes are greater than 1 then we cannot */
3332 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3333 AOP_SIZE (IC_LEFT (ic)) > 1)
3336 /* we can if the aops of the left & result match or
3337 if they are in registers and the registers are the
3339 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3343 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3351 /*-----------------------------------------------------------------*/
3352 /* addSign - complete with sign */
3353 /*-----------------------------------------------------------------*/
3355 addSign (operand * result, int offset, int sign)
3357 int size = (getDataSize (result) - offset);
3362 emitcode ("rlc", "a");
3363 emitcode ("subb", "a,acc");
3365 aopPut (AOP (result), "a", offset++);
3369 aopPut (AOP (result), zero, offset++);
3373 /*-----------------------------------------------------------------*/
3374 /* genMinusBits - generates code for subtraction of two bits */
3375 /*-----------------------------------------------------------------*/
3377 genMinusBits (iCode * ic)
3379 symbol *lbl = newiTempLabel (NULL);
3381 D(emitcode ("; genMinusBits",""));
3383 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3385 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3386 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3387 emitcode ("cpl", "c");
3388 emitcode ("", "%05d$:", (lbl->key + 100));
3389 outBitC (IC_RESULT (ic));
3393 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3394 emitcode ("subb", "a,acc");
3395 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3396 emitcode ("inc", "a");
3397 emitcode ("", "%05d$:", (lbl->key + 100));
3398 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3399 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3403 /*-----------------------------------------------------------------*/
3404 /* genMinus - generates code for subtraction */
3405 /*-----------------------------------------------------------------*/
3407 genMinus (iCode * ic)
3409 int size, offset = 0;
3411 D(emitcode ("; genMinus",""));
3413 aopOp (IC_LEFT (ic), ic, FALSE);
3414 aopOp (IC_RIGHT (ic), ic, FALSE);
3415 aopOp (IC_RESULT (ic), ic, TRUE);
3417 /* special cases :- */
3418 /* if both left & right are in bit space */
3419 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3420 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3426 /* if I can do an decrement instead
3427 of subtract then GOOD for ME */
3428 if (genMinusDec (ic) == TRUE)
3431 size = getDataSize (IC_RESULT (ic));
3433 /* if literal, add a,#-lit, else normal subb */
3434 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3436 unsigned long lit = 0L;
3438 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3443 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3444 /* first add without previous c */
3446 if (!size && lit==-1) {
3447 emitcode ("dec", "a");
3449 emitcode ("add", "a,#0x%02x",
3450 (unsigned int) (lit & 0x0FFL));
3453 emitcode ("addc", "a,#0x%02x",
3454 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3456 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3461 asmop *leftOp, *rightOp;
3463 leftOp = AOP(IC_LEFT(ic));
3464 rightOp = AOP(IC_RIGHT(ic));
3468 if (aopGetUsesAcc(rightOp, offset)) {
3469 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3470 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3472 emitcode( "setb", "c");
3474 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3475 emitcode("cpl", "a");
3477 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3480 emitcode ("subb", "a,%s",
3481 aopGet(rightOp, offset, FALSE, TRUE));
3484 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3489 adjustArithmeticResult (ic);
3492 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3493 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3494 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3498 /*-----------------------------------------------------------------*/
3499 /* genMultbits :- multiplication of bits */
3500 /*-----------------------------------------------------------------*/
3502 genMultbits (operand * left,
3506 D(emitcode ("; genMultbits",""));
3508 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3509 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3514 /*-----------------------------------------------------------------*/
3515 /* genMultOneByte : 8*8=8/16 bit multiplication */
3516 /*-----------------------------------------------------------------*/
3518 genMultOneByte (operand * left,
3522 sym_link *opetype = operandType (result);
3524 int size=AOP_SIZE(result);
3526 D(emitcode ("; genMultOneByte",""));
3528 if (size<1 || size>2) {
3529 // this should never happen
3530 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3531 AOP_SIZE(result), __FILE__, lineno);
3535 /* (if two literals: the value is computed before) */
3536 /* if one literal, literal on the right */
3537 if (AOP_TYPE (left) == AOP_LIT)
3542 //emitcode (";", "swapped left and right");
3545 if (SPEC_USIGN(opetype)
3546 // ignore the sign of left and right, what else can we do?
3547 || (SPEC_USIGN(operandType(left)) &&
3548 SPEC_USIGN(operandType(right)))) {
3549 // just an unsigned 8*8=8/16 multiply
3550 //emitcode (";","unsigned");
3551 // TODO: check for accumulator clash between left & right aops?
3552 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3553 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3554 emitcode ("mul", "ab");
3555 aopPut (AOP (result), "a", 0);
3557 aopPut (AOP (result), "b", 1);
3562 // we have to do a signed multiply
3564 //emitcode (";", "signed");
3565 emitcode ("clr", "F0"); // reset sign flag
3566 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3568 lbl=newiTempLabel(NULL);
3569 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3570 // left side is negative, 8-bit two's complement, this fails for -128
3571 emitcode ("setb", "F0"); // set sign flag
3572 emitcode ("cpl", "a");
3573 emitcode ("inc", "a");
3575 emitcode ("", "%05d$:", lbl->key+100);
3578 if (AOP_TYPE(right)==AOP_LIT) {
3579 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3580 /* AND literal negative */
3582 emitcode ("cpl", "F0"); // complement sign flag
3583 emitcode ("mov", "b,#0x%02x", -val);
3585 emitcode ("mov", "b,#0x%02x", val);
3588 lbl=newiTempLabel(NULL);
3589 emitcode ("mov", "b,a");
3590 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3591 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3592 // right side is negative, 8-bit two's complement
3593 emitcode ("cpl", "F0"); // complement sign flag
3594 emitcode ("cpl", "a");
3595 emitcode ("inc", "a");
3596 emitcode ("", "%05d$:", lbl->key+100);
3598 emitcode ("mul", "ab");
3600 lbl=newiTempLabel(NULL);
3601 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3602 // only ONE op was negative, we have to do a 8/16-bit two's complement
3603 emitcode ("cpl", "a"); // lsb
3605 emitcode ("inc", "a");
3607 emitcode ("add", "a,#1");
3608 emitcode ("xch", "a,b");
3609 emitcode ("cpl", "a"); // msb
3610 emitcode ("addc", "a,#0");
3611 emitcode ("xch", "a,b");
3614 emitcode ("", "%05d$:", lbl->key+100);
3615 aopPut (AOP (result), "a", 0);
3617 aopPut (AOP (result), "b", 1);
3621 /*-----------------------------------------------------------------*/
3622 /* genMult - generates code for multiplication */
3623 /*-----------------------------------------------------------------*/
3625 genMult (iCode * ic)
3627 operand *left = IC_LEFT (ic);
3628 operand *right = IC_RIGHT (ic);
3629 operand *result = IC_RESULT (ic);
3631 D(emitcode ("; genMult",""));
3633 /* assign the amsops */
3634 aopOp (left, ic, FALSE);
3635 aopOp (right, ic, FALSE);
3636 aopOp (result, ic, TRUE);
3638 /* special cases first */
3640 if (AOP_TYPE (left) == AOP_CRY &&
3641 AOP_TYPE (right) == AOP_CRY)
3643 genMultbits (left, right, result);
3647 /* if both are of size == 1 */
3648 #if 0 // one of them can be a sloc shared with the result
3649 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3651 if (getSize(operandType(left)) == 1 &&
3652 getSize(operandType(right)) == 1)
3655 genMultOneByte (left, right, result);
3659 /* should have been converted to function call */
3660 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3661 getSize(OP_SYMBOL(right)->type));
3665 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3666 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667 freeAsmop (result, NULL, ic, TRUE);
3670 /*-----------------------------------------------------------------*/
3671 /* genDivbits :- division of bits */
3672 /*-----------------------------------------------------------------*/
3674 genDivbits (operand * left,
3681 D(emitcode ("; genDivbits",""));
3683 /* the result must be bit */
3684 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3685 l = aopGet (AOP (left), 0, FALSE, FALSE);
3689 emitcode ("div", "ab");
3690 emitcode ("rrc", "a");
3691 aopPut (AOP (result), "c", 0);
3694 /*-----------------------------------------------------------------*/
3695 /* genDivOneByte : 8 bit division */
3696 /*-----------------------------------------------------------------*/
3698 genDivOneByte (operand * left,
3702 sym_link *opetype = operandType (result);
3707 D(emitcode ("; genDivOneByte",""));
3709 size = AOP_SIZE (result) - 1;
3711 /* signed or unsigned */
3712 if (SPEC_USIGN (opetype))
3714 /* unsigned is easy */
3715 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3716 l = aopGet (AOP (left), 0, FALSE, FALSE);
3718 emitcode ("div", "ab");
3719 aopPut (AOP (result), "a", 0);
3721 aopPut (AOP (result), zero, offset++);
3725 /* signed is a little bit more difficult */
3727 /* save the signs of the operands */
3728 l = aopGet (AOP (left), 0, FALSE, FALSE);
3730 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3731 emitcode ("push", "acc"); /* save it on the stack */
3733 /* now sign adjust for both left & right */
3734 l = aopGet (AOP (right), 0, FALSE, FALSE);
3736 lbl = newiTempLabel (NULL);
3737 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3738 emitcode ("cpl", "a");
3739 emitcode ("inc", "a");
3740 emitcode ("", "%05d$:", (lbl->key + 100));
3741 emitcode ("mov", "b,a");
3743 /* sign adjust left side */
3744 l = aopGet (AOP (left), 0, FALSE, FALSE);
3747 lbl = newiTempLabel (NULL);
3748 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3749 emitcode ("cpl", "a");
3750 emitcode ("inc", "a");
3751 emitcode ("", "%05d$:", (lbl->key + 100));
3753 /* now the division */
3754 emitcode ("div", "ab");
3755 /* we are interested in the lower order
3757 emitcode ("mov", "b,a");
3758 lbl = newiTempLabel (NULL);
3759 emitcode ("pop", "acc");
3760 /* if there was an over flow we don't
3761 adjust the sign of the result */
3762 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3763 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3765 emitcode ("clr", "a");
3766 emitcode ("subb", "a,b");
3767 emitcode ("mov", "b,a");
3768 emitcode ("", "%05d$:", (lbl->key + 100));
3770 /* now we are done */
3771 aopPut (AOP (result), "b", 0);
3774 emitcode ("mov", "c,b.7");
3775 emitcode ("subb", "a,acc");
3778 aopPut (AOP (result), "a", offset++);
3782 /*-----------------------------------------------------------------*/
3783 /* genDiv - generates code for division */
3784 /*-----------------------------------------------------------------*/
3788 operand *left = IC_LEFT (ic);
3789 operand *right = IC_RIGHT (ic);
3790 operand *result = IC_RESULT (ic);
3792 D(emitcode ("; genDiv",""));
3794 /* assign the amsops */
3795 aopOp (left, ic, FALSE);
3796 aopOp (right, ic, FALSE);
3797 aopOp (result, ic, TRUE);
3799 /* special cases first */
3801 if (AOP_TYPE (left) == AOP_CRY &&
3802 AOP_TYPE (right) == AOP_CRY)
3804 genDivbits (left, right, result);
3808 /* if both are of size == 1 */
3809 if (AOP_SIZE (left) == 1 &&
3810 AOP_SIZE (right) == 1)
3812 genDivOneByte (left, right, result);
3816 /* should have been converted to function call */
3819 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3820 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3821 freeAsmop (result, NULL, ic, TRUE);
3824 /*-----------------------------------------------------------------*/
3825 /* genModbits :- modulus of bits */
3826 /*-----------------------------------------------------------------*/
3828 genModbits (operand * left,
3835 D(emitcode ("; genModbits",""));
3837 /* the result must be bit */
3838 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3839 l = aopGet (AOP (left), 0, FALSE, FALSE);
3843 emitcode ("div", "ab");
3844 emitcode ("mov", "a,b");
3845 emitcode ("rrc", "a");
3846 aopPut (AOP (result), "c", 0);
3849 /*-----------------------------------------------------------------*/
3850 /* genModOneByte : 8 bit modulus */
3851 /*-----------------------------------------------------------------*/
3853 genModOneByte (operand * left,
3857 sym_link *opetype = operandType (result);
3861 D(emitcode ("; genModOneByte",""));
3863 /* signed or unsigned */
3864 if (SPEC_USIGN (opetype))
3866 /* unsigned is easy */
3867 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3868 l = aopGet (AOP (left), 0, FALSE, FALSE);
3870 emitcode ("div", "ab");
3871 aopPut (AOP (result), "b", 0);
3875 /* signed is a little bit more difficult */
3877 /* save the signs of the operands */
3878 l = aopGet (AOP (left), 0, FALSE, FALSE);
3881 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3882 emitcode ("push", "acc"); /* save it on the stack */
3884 /* now sign adjust for both left & right */
3885 l = aopGet (AOP (right), 0, FALSE, FALSE);
3888 lbl = newiTempLabel (NULL);
3889 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3890 emitcode ("cpl", "a");
3891 emitcode ("inc", "a");
3892 emitcode ("", "%05d$:", (lbl->key + 100));
3893 emitcode ("mov", "b,a");
3895 /* sign adjust left side */
3896 l = aopGet (AOP (left), 0, FALSE, FALSE);
3899 lbl = newiTempLabel (NULL);
3900 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3901 emitcode ("cpl", "a");
3902 emitcode ("inc", "a");
3903 emitcode ("", "%05d$:", (lbl->key + 100));
3905 /* now the multiplication */
3906 emitcode ("div", "ab");
3907 /* we are interested in the lower order
3909 lbl = newiTempLabel (NULL);
3910 emitcode ("pop", "acc");
3911 /* if there was an over flow we don't
3912 adjust the sign of the result */
3913 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3914 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3916 emitcode ("clr", "a");
3917 emitcode ("subb", "a,b");
3918 emitcode ("mov", "b,a");
3919 emitcode ("", "%05d$:", (lbl->key + 100));
3921 /* now we are done */
3922 aopPut (AOP (result), "b", 0);
3926 /*-----------------------------------------------------------------*/
3927 /* genMod - generates code for division */
3928 /*-----------------------------------------------------------------*/
3932 operand *left = IC_LEFT (ic);
3933 operand *right = IC_RIGHT (ic);
3934 operand *result = IC_RESULT (ic);
3936 D(emitcode ("; genMod",""));
3938 /* assign the amsops */
3939 aopOp (left, ic, FALSE);
3940 aopOp (right, ic, FALSE);
3941 aopOp (result, ic, TRUE);
3943 /* special cases first */
3945 if (AOP_TYPE (left) == AOP_CRY &&
3946 AOP_TYPE (right) == AOP_CRY)
3948 genModbits (left, right, result);
3952 /* if both are of size == 1 */
3953 if (AOP_SIZE (left) == 1 &&
3954 AOP_SIZE (right) == 1)
3956 genModOneByte (left, right, result);
3960 /* should have been converted to function call */
3964 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3965 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3966 freeAsmop (result, NULL, ic, TRUE);
3969 /*-----------------------------------------------------------------*/
3970 /* genIfxJump :- will create a jump depending on the ifx */
3971 /*-----------------------------------------------------------------*/
3973 genIfxJump (iCode * ic, char *jval)
3976 symbol *tlbl = newiTempLabel (NULL);
3979 D(emitcode ("; genIfxJump",""));
3981 /* if true label then we jump if condition
3985 jlbl = IC_TRUE (ic);
3986 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3987 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3991 /* false label is present */
3992 jlbl = IC_FALSE (ic);
3993 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3994 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3996 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3997 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3999 emitcode (inst, "%05d$", tlbl->key + 100);
4000 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4001 emitcode ("", "%05d$:", tlbl->key + 100);
4003 /* mark the icode as generated */
4007 /*-----------------------------------------------------------------*/
4008 /* genCmp :- greater or less than comparison */
4009 /*-----------------------------------------------------------------*/
4011 genCmp (operand * left, operand * right,
4012 operand * result, iCode * ifx, int sign, iCode *ic)
4014 int size, offset = 0;
4015 unsigned long lit = 0L;
4017 D(emitcode ("; genCmp",""));
4019 /* if left & right are bit variables */
4020 if (AOP_TYPE (left) == AOP_CRY &&
4021 AOP_TYPE (right) == AOP_CRY)
4023 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4024 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4028 /* subtract right from left if at the
4029 end the carry flag is set then we know that
4030 left is greater than right */
4031 size = max (AOP_SIZE (left), AOP_SIZE (right));
4033 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4034 if ((size == 1) && !sign &&
4035 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4037 symbol *lbl = newiTempLabel (NULL);
4038 emitcode ("cjne", "%s,%s,%05d$",
4039 aopGet (AOP (left), offset, FALSE, FALSE),
4040 aopGet (AOP (right), offset, FALSE, FALSE),
4042 emitcode ("", "%05d$:", lbl->key + 100);
4046 if (AOP_TYPE (right) == AOP_LIT)
4048 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4049 /* optimize if(x < 0) or if(x >= 0) */
4058 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4059 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4061 genIfxJump (ifx, "acc.7");
4065 emitcode ("rlc", "a");
4073 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4074 if (sign && size == 0)
4076 emitcode ("xrl", "a,#0x80");
4077 if (AOP_TYPE (right) == AOP_LIT)
4079 unsigned long lit = (unsigned long)
4080 floatFromVal (AOP (right)->aopu.aop_lit);
4081 emitcode ("subb", "a,#0x%02x",
4082 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4086 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4087 emitcode ("xrl", "b,#0x80");
4088 emitcode ("subb", "a,b");
4092 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4098 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4099 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4100 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4106 /* if the result is used in the next
4107 ifx conditional branch then generate
4108 code a little differently */
4110 genIfxJump (ifx, "c");
4113 /* leave the result in acc */
4117 /*-----------------------------------------------------------------*/
4118 /* genCmpGt :- greater than comparison */
4119 /*-----------------------------------------------------------------*/
4121 genCmpGt (iCode * ic, iCode * ifx)
4123 operand *left, *right, *result;
4124 sym_link *letype, *retype;
4127 D(emitcode ("; genCmpGt",""));
4129 left = IC_LEFT (ic);
4130 right = IC_RIGHT (ic);
4131 result = IC_RESULT (ic);
4133 letype = getSpec (operandType (left));
4134 retype = getSpec (operandType (right));
4135 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4136 /* assign the amsops */
4137 aopOp (left, ic, FALSE);
4138 aopOp (right, ic, FALSE);
4139 aopOp (result, ic, TRUE);
4141 genCmp (right, left, result, ifx, sign,ic);
4143 freeAsmop (result, NULL, ic, TRUE);
4146 /*-----------------------------------------------------------------*/
4147 /* genCmpLt - less than comparisons */
4148 /*-----------------------------------------------------------------*/
4150 genCmpLt (iCode * ic, iCode * ifx)
4152 operand *left, *right, *result;
4153 sym_link *letype, *retype;
4156 D(emitcode ("; genCmpLt",""));
4158 left = IC_LEFT (ic);
4159 right = IC_RIGHT (ic);
4160 result = IC_RESULT (ic);
4162 letype = getSpec (operandType (left));
4163 retype = getSpec (operandType (right));
4164 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4166 /* assign the amsops */
4167 aopOp (left, ic, FALSE);
4168 aopOp (right, ic, FALSE);
4169 aopOp (result, ic, TRUE);
4171 genCmp (left, right, result, ifx, sign,ic);
4173 freeAsmop (result, NULL, ic, TRUE);
4176 /*-----------------------------------------------------------------*/
4177 /* gencjneshort - compare and jump if not equal */
4178 /*-----------------------------------------------------------------*/
4180 gencjneshort (operand * left, operand * right, symbol * lbl)
4182 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4184 unsigned long lit = 0L;
4186 /* if the left side is a literal or
4187 if the right is in a pointer register and left
4189 if ((AOP_TYPE (left) == AOP_LIT) ||
4190 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4196 if (AOP_TYPE (right) == AOP_LIT)
4197 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4199 /* if the right side is a literal then anything goes */
4200 if (AOP_TYPE (right) == AOP_LIT &&
4201 AOP_TYPE (left) != AOP_DIR)
4205 emitcode ("cjne", "%s,%s,%05d$",
4206 aopGet (AOP (left), offset, FALSE, FALSE),
4207 aopGet (AOP (right), offset, FALSE, FALSE),
4213 /* if the right side is in a register or in direct space or
4214 if the left is a pointer register & right is not */
4215 else if (AOP_TYPE (right) == AOP_REG ||
4216 AOP_TYPE (right) == AOP_DIR ||
4217 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4218 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4222 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4223 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4224 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4225 emitcode ("jnz", "%05d$", lbl->key + 100);
4227 emitcode ("cjne", "a,%s,%05d$",
4228 aopGet (AOP (right), offset, FALSE, TRUE),
4235 /* right is a pointer reg need both a & b */
4238 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4239 if (strcmp (l, "b"))
4240 emitcode ("mov", "b,%s", l);
4241 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4242 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4248 /*-----------------------------------------------------------------*/
4249 /* gencjne - compare and jump if not equal */
4250 /*-----------------------------------------------------------------*/
4252 gencjne (operand * left, operand * right, symbol * lbl)
4254 symbol *tlbl = newiTempLabel (NULL);
4256 gencjneshort (left, right, lbl);
4258 emitcode ("mov", "a,%s", one);
4259 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4260 emitcode ("", "%05d$:", lbl->key + 100);
4261 emitcode ("clr", "a");
4262 emitcode ("", "%05d$:", tlbl->key + 100);
4265 /*-----------------------------------------------------------------*/
4266 /* genCmpEq - generates code for equal to */
4267 /*-----------------------------------------------------------------*/
4269 genCmpEq (iCode * ic, iCode * ifx)
4271 operand *left, *right, *result;
4273 D(emitcode ("; genCmpEq",""));
4275 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4276 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4277 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4279 /* if literal, literal on the right or
4280 if the right is in a pointer register and left
4282 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4283 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4285 operand *t = IC_RIGHT (ic);
4286 IC_RIGHT (ic) = IC_LEFT (ic);
4290 if (ifx && !AOP_SIZE (result))
4293 /* if they are both bit variables */
4294 if (AOP_TYPE (left) == AOP_CRY &&
4295 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4297 if (AOP_TYPE (right) == AOP_LIT)
4299 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4303 emitcode ("cpl", "c");
4307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4311 emitcode ("clr", "c");
4313 /* AOP_TYPE(right) == AOP_CRY */
4317 symbol *lbl = newiTempLabel (NULL);
4318 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4319 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4320 emitcode ("cpl", "c");
4321 emitcode ("", "%05d$:", (lbl->key + 100));
4323 /* if true label then we jump if condition
4325 tlbl = newiTempLabel (NULL);
4328 emitcode ("jnc", "%05d$", tlbl->key + 100);
4329 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4333 emitcode ("jc", "%05d$", tlbl->key + 100);
4334 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4336 emitcode ("", "%05d$:", tlbl->key + 100);
4340 tlbl = newiTempLabel (NULL);
4341 gencjneshort (left, right, tlbl);
4344 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4345 emitcode ("", "%05d$:", tlbl->key + 100);
4349 symbol *lbl = newiTempLabel (NULL);
4350 emitcode ("sjmp", "%05d$", lbl->key + 100);
4351 emitcode ("", "%05d$:", tlbl->key + 100);
4352 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4353 emitcode ("", "%05d$:", lbl->key + 100);
4356 /* mark the icode as generated */
4361 /* if they are both bit variables */
4362 if (AOP_TYPE (left) == AOP_CRY &&
4363 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4365 if (AOP_TYPE (right) == AOP_LIT)
4367 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4370 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4371 emitcode ("cpl", "c");
4375 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4379 emitcode ("clr", "c");
4381 /* AOP_TYPE(right) == AOP_CRY */
4385 symbol *lbl = newiTempLabel (NULL);
4386 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4387 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4388 emitcode ("cpl", "c");
4389 emitcode ("", "%05d$:", (lbl->key + 100));
4392 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4399 genIfxJump (ifx, "c");
4402 /* if the result is used in an arithmetic operation
4403 then put the result in place */
4408 gencjne (left, right, newiTempLabel (NULL));
4409 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4411 aopPut (AOP (result), "a", 0);
4416 genIfxJump (ifx, "a");
4419 /* if the result is used in an arithmetic operation
4420 then put the result in place */
4421 if (AOP_TYPE (result) != AOP_CRY)
4423 /* leave the result in acc */
4427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 freeAsmop (result, NULL, ic, TRUE);
4432 /*-----------------------------------------------------------------*/
4433 /* ifxForOp - returns the icode containing the ifx for operand */
4434 /*-----------------------------------------------------------------*/
4436 ifxForOp (operand * op, iCode * ic)
4438 /* if true symbol then needs to be assigned */
4439 if (IS_TRUE_SYMOP (op))
4442 /* if this has register type condition and
4443 the next instruction is ifx with the same operand
4444 and live to of the operand is upto the ifx only then */
4446 ic->next->op == IFX &&
4447 IC_COND (ic->next)->key == op->key &&
4448 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4454 /*-----------------------------------------------------------------*/
4455 /* hasInc - operand is incremented before any other use */
4456 /*-----------------------------------------------------------------*/
4458 hasInc (operand *op, iCode *ic,int osize)
4460 sym_link *type = operandType(op);
4461 sym_link *retype = getSpec (type);
4462 iCode *lic = ic->next;
4465 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4466 if (!IS_SYMOP(op)) return NULL;
4468 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4469 if (IS_AGGREGATE(type->next)) return NULL;
4470 if (osize != (isize = getSize(type->next))) return NULL;
4473 /* if operand of the form op = op + <sizeof *op> */
4474 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4475 isOperandEqual(IC_RESULT(lic),op) &&
4476 isOperandLiteral(IC_RIGHT(lic)) &&
4477 operandLitValue(IC_RIGHT(lic)) == isize) {
4480 /* if the operand used or deffed */
4481 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4484 /* if GOTO or IFX */
4485 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4491 /*-----------------------------------------------------------------*/
4492 /* genAndOp - for && operation */
4493 /*-----------------------------------------------------------------*/
4495 genAndOp (iCode * ic)
4497 operand *left, *right, *result;
4500 D(emitcode ("; genAndOp",""));
4502 /* note here that && operations that are in an
4503 if statement are taken away by backPatchLabels
4504 only those used in arthmetic operations remain */
4505 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4506 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4507 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4509 /* if both are bit variables */
4510 if (AOP_TYPE (left) == AOP_CRY &&
4511 AOP_TYPE (right) == AOP_CRY)
4513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4514 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4519 tlbl = newiTempLabel (NULL);
4521 emitcode ("jz", "%05d$", tlbl->key + 100);
4523 emitcode ("", "%05d$:", tlbl->key + 100);
4527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4528 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4529 freeAsmop (result, NULL, ic, TRUE);
4533 /*-----------------------------------------------------------------*/
4534 /* genOrOp - for || operation */
4535 /*-----------------------------------------------------------------*/
4537 genOrOp (iCode * ic)
4539 operand *left, *right, *result;
4542 D(emitcode ("; genOrOp",""));
4544 /* note here that || operations that are in an
4545 if statement are taken away by backPatchLabels
4546 only those used in arthmetic operations remain */
4547 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4548 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4549 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4551 /* if both are bit variables */
4552 if (AOP_TYPE (left) == AOP_CRY &&
4553 AOP_TYPE (right) == AOP_CRY)
4555 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4556 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4561 tlbl = newiTempLabel (NULL);
4563 emitcode ("jnz", "%05d$", tlbl->key + 100);
4565 emitcode ("", "%05d$:", tlbl->key + 100);
4569 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (result, NULL, ic, TRUE);
4574 /*-----------------------------------------------------------------*/
4575 /* isLiteralBit - test if lit == 2^n */
4576 /*-----------------------------------------------------------------*/
4578 isLiteralBit (unsigned long lit)
4580 unsigned long pw[32] =
4581 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4582 0x100L, 0x200L, 0x400L, 0x800L,
4583 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4584 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4585 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4586 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4587 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4590 for (idx = 0; idx < 32; idx++)
4596 /*-----------------------------------------------------------------*/
4597 /* continueIfTrue - */
4598 /*-----------------------------------------------------------------*/
4600 continueIfTrue (iCode * ic)
4603 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4607 /*-----------------------------------------------------------------*/
4609 /*-----------------------------------------------------------------*/
4611 jumpIfTrue (iCode * ic)
4614 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4618 /*-----------------------------------------------------------------*/
4619 /* jmpTrueOrFalse - */
4620 /*-----------------------------------------------------------------*/
4622 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4624 // ugly but optimized by peephole
4627 symbol *nlbl = newiTempLabel (NULL);
4628 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4629 emitcode ("", "%05d$:", tlbl->key + 100);
4630 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4631 emitcode ("", "%05d$:", nlbl->key + 100);
4635 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4636 emitcode ("", "%05d$:", tlbl->key + 100);
4641 /*-----------------------------------------------------------------*/
4642 /* genAnd - code for and */
4643 /*-----------------------------------------------------------------*/
4645 genAnd (iCode * ic, iCode * ifx)
4647 operand *left, *right, *result;
4648 int size, offset = 0;
4649 unsigned long lit = 0L;
4653 D(emitcode ("; genAnd",""));
4655 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4656 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4657 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4660 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4662 AOP_TYPE (left), AOP_TYPE (right));
4663 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4665 AOP_SIZE (left), AOP_SIZE (right));
4668 /* if left is a literal & right is not then exchange them */
4669 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4670 AOP_NEEDSACC (left))
4672 operand *tmp = right;
4677 /* if result = right then exchange them */
4678 if (sameRegs (AOP (result), AOP (right)))
4680 operand *tmp = right;
4685 /* if right is bit then exchange them */
4686 if (AOP_TYPE (right) == AOP_CRY &&
4687 AOP_TYPE (left) != AOP_CRY)
4689 operand *tmp = right;
4693 if (AOP_TYPE (right) == AOP_LIT)
4694 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4696 size = AOP_SIZE (result);
4699 // result = bit & yy;
4700 if (AOP_TYPE (left) == AOP_CRY)
4702 // c = bit & literal;
4703 if (AOP_TYPE (right) == AOP_LIT)
4707 if (size && sameRegs (AOP (result), AOP (left)))
4710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4715 if (size && (AOP_TYPE (result) == AOP_CRY))
4717 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4720 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4725 emitcode ("clr", "c");
4730 if (AOP_TYPE (right) == AOP_CRY)
4733 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4734 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4739 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4741 emitcode ("rrc", "a");
4742 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4750 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4751 genIfxJump (ifx, "c");
4755 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4756 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4757 if ((AOP_TYPE (right) == AOP_LIT) &&
4758 (AOP_TYPE (result) == AOP_CRY) &&
4759 (AOP_TYPE (left) != AOP_CRY))
4761 int posbit = isLiteralBit (lit);
4766 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4769 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4775 sprintf (buffer, "acc.%d", posbit & 0x07);
4776 genIfxJump (ifx, buffer);
4783 symbol *tlbl = newiTempLabel (NULL);
4784 int sizel = AOP_SIZE (left);
4786 emitcode ("setb", "c");
4789 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4791 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4793 if ((posbit = isLiteralBit (bytelit)) != 0)
4794 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4797 if (bytelit != 0x0FFL)
4798 emitcode ("anl", "a,%s",
4799 aopGet (AOP (right), offset, FALSE, TRUE));
4800 emitcode ("jnz", "%05d$", tlbl->key + 100);
4805 // bit = left & literal
4808 emitcode ("clr", "c");
4809 emitcode ("", "%05d$:", tlbl->key + 100);
4811 // if(left & literal)
4815 jmpTrueOrFalse (ifx, tlbl);
4823 /* if left is same as result */
4824 if (sameRegs (AOP (result), AOP (left)))
4826 for (; size--; offset++)
4828 if (AOP_TYPE (right) == AOP_LIT)
4830 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4832 else if (bytelit == 0)
4833 aopPut (AOP (result), zero, offset);
4834 else if (IS_AOP_PREG (result))
4836 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4837 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4838 aopPut (AOP (result), "a", offset);
4841 emitcode ("anl", "%s,%s",
4842 aopGet (AOP (left), offset, FALSE, TRUE),
4843 aopGet (AOP (right), offset, FALSE, FALSE));
4847 if (AOP_TYPE (left) == AOP_ACC)
4848 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4851 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4852 if (IS_AOP_PREG (result))
4854 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4855 aopPut (AOP (result), "a", offset);
4859 emitcode ("anl", "%s,a",
4860 aopGet (AOP (left), offset, FALSE, TRUE));
4867 // left & result in different registers
4868 if (AOP_TYPE (result) == AOP_CRY)
4871 // if(size), result in bit
4872 // if(!size && ifx), conditional oper: if(left & right)
4873 symbol *tlbl = newiTempLabel (NULL);
4874 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4876 emitcode ("setb", "c");
4879 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4880 emitcode ("anl", "a,%s",
4881 aopGet (AOP (right), offset, FALSE, FALSE));
4883 if (AOP_TYPE(left)==AOP_ACC) {
4884 emitcode("mov", "b,a");
4885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4886 emitcode("anl", "a,b");
4888 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4889 emitcode ("anl", "a,%s",
4890 aopGet (AOP (left), offset, FALSE, FALSE));
4893 emitcode ("jnz", "%05d$", tlbl->key + 100);
4899 emitcode ("", "%05d$:", tlbl->key + 100);
4903 jmpTrueOrFalse (ifx, tlbl);
4907 for (; (size--); offset++)
4910 // result = left & right
4911 if (AOP_TYPE (right) == AOP_LIT)
4913 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4915 aopPut (AOP (result),
4916 aopGet (AOP (left), offset, FALSE, FALSE),
4920 else if (bytelit == 0)
4922 aopPut (AOP (result), zero, offset);
4926 // faster than result <- left, anl result,right
4927 // and better if result is SFR
4928 if (AOP_TYPE (left) == AOP_ACC)
4929 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4933 emitcode ("anl", "a,%s",
4934 aopGet (AOP (left), offset, FALSE, FALSE));
4936 aopPut (AOP (result), "a", offset);
4942 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genOr - code for or */
4949 /*-----------------------------------------------------------------*/
4951 genOr (iCode * ic, iCode * ifx)
4953 operand *left, *right, *result;
4954 int size, offset = 0;
4955 unsigned long lit = 0L;
4957 D(emitcode ("; genOr",""));
4959 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4960 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4961 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4964 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4966 AOP_TYPE (left), AOP_TYPE (right));
4967 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4969 AOP_SIZE (left), AOP_SIZE (right));
4972 /* if left is a literal & right is not then exchange them */
4973 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4974 AOP_NEEDSACC (left))
4976 operand *tmp = right;
4981 /* if result = right then exchange them */
4982 if (sameRegs (AOP (result), AOP (right)))
4984 operand *tmp = right;
4989 /* if right is bit then exchange them */
4990 if (AOP_TYPE (right) == AOP_CRY &&
4991 AOP_TYPE (left) != AOP_CRY)
4993 operand *tmp = right;
4997 if (AOP_TYPE (right) == AOP_LIT)
4998 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5000 size = AOP_SIZE (result);
5004 if (AOP_TYPE (left) == AOP_CRY)
5006 if (AOP_TYPE (right) == AOP_LIT)
5008 // c = bit | literal;
5011 // lit != 0 => result = 1
5012 if (AOP_TYPE (result) == AOP_CRY)
5015 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5017 continueIfTrue (ifx);
5020 emitcode ("setb", "c");
5024 // lit == 0 => result = left
5025 if (size && sameRegs (AOP (result), AOP (left)))
5027 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5032 if (AOP_TYPE (right) == AOP_CRY)
5035 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5036 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5041 symbol *tlbl = newiTempLabel (NULL);
5042 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5043 emitcode ("setb", "c");
5044 emitcode ("jb", "%s,%05d$",
5045 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5047 emitcode ("jnz", "%05d$", tlbl->key + 100);
5048 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5050 jmpTrueOrFalse (ifx, tlbl);
5056 emitcode ("", "%05d$:", tlbl->key + 100);
5065 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5066 genIfxJump (ifx, "c");
5070 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5071 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5072 if ((AOP_TYPE (right) == AOP_LIT) &&
5073 (AOP_TYPE (result) == AOP_CRY) &&
5074 (AOP_TYPE (left) != AOP_CRY))
5080 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5082 continueIfTrue (ifx);
5087 // lit = 0, result = boolean(left)
5089 emitcode ("setb", "c");
5093 symbol *tlbl = newiTempLabel (NULL);
5094 emitcode ("jnz", "%05d$", tlbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5100 genIfxJump (ifx, "a");
5108 /* if left is same as result */
5109 if (sameRegs (AOP (result), AOP (left)))
5111 for (; size--; offset++)
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5117 else if (IS_AOP_PREG (left))
5119 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5120 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5121 aopPut (AOP (result), "a", offset);
5124 emitcode ("orl", "%s,%s",
5125 aopGet (AOP (left), offset, FALSE, TRUE),
5126 aopGet (AOP (right), offset, FALSE, FALSE));
5130 if (AOP_TYPE (left) == AOP_ACC)
5131 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5134 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5135 if (IS_AOP_PREG (left))
5137 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5138 aopPut (AOP (result), "a", offset);
5141 emitcode ("orl", "%s,a",
5142 aopGet (AOP (left), offset, FALSE, TRUE));
5149 // left & result in different registers
5150 if (AOP_TYPE (result) == AOP_CRY)
5153 // if(size), result in bit
5154 // if(!size && ifx), conditional oper: if(left | right)
5155 symbol *tlbl = newiTempLabel (NULL);
5156 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5158 emitcode ("setb", "c");
5161 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5162 emitcode ("orl", "a,%s",
5163 aopGet (AOP (right), offset, FALSE, FALSE));
5165 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5166 emitcode ("orl", "a,%s",
5167 aopGet (AOP (left), offset, FALSE, FALSE));
5169 emitcode ("jnz", "%05d$", tlbl->key + 100);
5175 emitcode ("", "%05d$:", tlbl->key + 100);
5179 jmpTrueOrFalse (ifx, tlbl);
5182 for (; (size--); offset++)
5185 // result = left & right
5186 if (AOP_TYPE (right) == AOP_LIT)
5188 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5190 aopPut (AOP (result),
5191 aopGet (AOP (left), offset, FALSE, FALSE),
5196 // faster than result <- left, anl result,right
5197 // and better if result is SFR
5198 if (AOP_TYPE (left) == AOP_ACC)
5199 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5202 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5203 emitcode ("orl", "a,%s",
5204 aopGet (AOP (left), offset, FALSE, FALSE));
5206 aopPut (AOP (result), "a", offset);
5211 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5212 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5213 freeAsmop (result, NULL, ic, TRUE);
5216 /*-----------------------------------------------------------------*/
5217 /* genXor - code for xclusive or */
5218 /*-----------------------------------------------------------------*/
5220 genXor (iCode * ic, iCode * ifx)
5222 operand *left, *right, *result;
5223 int size, offset = 0;
5224 unsigned long lit = 0L;
5226 D(emitcode ("; genXor",""));
5228 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5229 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5230 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5233 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5235 AOP_TYPE (left), AOP_TYPE (right));
5236 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5238 AOP_SIZE (left), AOP_SIZE (right));
5241 /* if left is a literal & right is not ||
5242 if left needs acc & right does not */
5243 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5244 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5246 operand *tmp = right;
5251 /* if result = right then exchange them */
5252 if (sameRegs (AOP (result), AOP (right)))
5254 operand *tmp = right;
5259 /* if right is bit then exchange them */
5260 if (AOP_TYPE (right) == AOP_CRY &&
5261 AOP_TYPE (left) != AOP_CRY)
5263 operand *tmp = right;
5267 if (AOP_TYPE (right) == AOP_LIT)
5268 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5270 size = AOP_SIZE (result);
5274 if (AOP_TYPE (left) == AOP_CRY)
5276 if (AOP_TYPE (right) == AOP_LIT)
5278 // c = bit & literal;
5281 // lit>>1 != 0 => result = 1
5282 if (AOP_TYPE (result) == AOP_CRY)
5285 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5287 continueIfTrue (ifx);
5290 emitcode ("setb", "c");
5297 // lit == 0, result = left
5298 if (size && sameRegs (AOP (result), AOP (left)))
5300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304 // lit == 1, result = not(left)
5305 if (size && sameRegs (AOP (result), AOP (left)))
5307 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5313 emitcode ("cpl", "c");
5322 symbol *tlbl = newiTempLabel (NULL);
5323 if (AOP_TYPE (right) == AOP_CRY)
5326 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5330 int sizer = AOP_SIZE (right);
5332 // if val>>1 != 0, result = 1
5333 emitcode ("setb", "c");
5336 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5338 // test the msb of the lsb
5339 emitcode ("anl", "a,#0xfe");
5340 emitcode ("jnz", "%05d$", tlbl->key + 100);
5344 emitcode ("rrc", "a");
5346 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5347 emitcode ("cpl", "c");
5348 emitcode ("", "%05d$:", (tlbl->key + 100));
5355 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5356 genIfxJump (ifx, "c");
5360 if (sameRegs (AOP (result), AOP (left)))
5362 /* if left is same as result */
5363 for (; size--; offset++)
5365 if (AOP_TYPE (right) == AOP_LIT)
5367 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5369 else if (IS_AOP_PREG (left))
5371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5372 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5373 aopPut (AOP (result), "a", offset);
5376 emitcode ("xrl", "%s,%s",
5377 aopGet (AOP (left), offset, FALSE, TRUE),
5378 aopGet (AOP (right), offset, FALSE, FALSE));
5382 if (AOP_TYPE (left) == AOP_ACC)
5383 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5386 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5387 if (IS_AOP_PREG (left))
5389 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5390 aopPut (AOP (result), "a", offset);
5393 emitcode ("xrl", "%s,a",
5394 aopGet (AOP (left), offset, FALSE, TRUE));
5401 // left & result in different registers
5402 if (AOP_TYPE (result) == AOP_CRY)
5405 // if(size), result in bit
5406 // if(!size && ifx), conditional oper: if(left ^ right)
5407 symbol *tlbl = newiTempLabel (NULL);
5408 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5410 emitcode ("setb", "c");
5413 if ((AOP_TYPE (right) == AOP_LIT) &&
5414 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5416 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5420 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5421 emitcode ("xrl", "a,%s",
5422 aopGet (AOP (right), offset, FALSE, FALSE));
5424 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5425 emitcode ("xrl", "a,%s",
5426 aopGet (AOP (left), offset, FALSE, FALSE));
5429 emitcode ("jnz", "%05d$", tlbl->key + 100);
5435 emitcode ("", "%05d$:", tlbl->key + 100);
5439 jmpTrueOrFalse (ifx, tlbl);
5442 for (; (size--); offset++)
5445 // result = left & right
5446 if (AOP_TYPE (right) == AOP_LIT)
5448 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5450 aopPut (AOP (result),
5451 aopGet (AOP (left), offset, FALSE, FALSE),
5456 // faster than result <- left, anl result,right
5457 // and better if result is SFR
5458 if (AOP_TYPE (left) == AOP_ACC)
5459 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5462 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5463 emitcode ("xrl", "a,%s",
5464 aopGet (AOP (left), offset, FALSE, TRUE));
5466 aopPut (AOP (result), "a", offset);
5471 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473 freeAsmop (result, NULL, ic, TRUE);
5476 /*-----------------------------------------------------------------*/
5477 /* genInline - write the inline code out */
5478 /*-----------------------------------------------------------------*/
5480 genInline (iCode * ic)
5482 char *buffer, *bp, *bp1;
5484 D(emitcode ("; genInline",""));
5486 _G.inLine += (!options.asmpeep);
5488 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5489 strcpy (buffer, IC_INLINE (ic));
5491 /* emit each line as a code */
5516 /* emitcode("",buffer); */
5517 _G.inLine -= (!options.asmpeep);
5520 /*-----------------------------------------------------------------*/
5521 /* genRRC - rotate right with carry */
5522 /*-----------------------------------------------------------------*/
5526 operand *left, *result;
5527 int size, offset = 0;
5530 D(emitcode ("; genRRC",""));
5532 /* rotate right with carry */
5533 left = IC_LEFT (ic);
5534 result = IC_RESULT (ic);
5535 aopOp (left, ic, FALSE);
5536 aopOp (result, ic, FALSE);
5538 /* move it to the result */
5539 size = AOP_SIZE (result);
5541 if (size == 1) { /* special case for 1 byte */
5542 l = aopGet (AOP (left), offset, FALSE, FALSE);
5544 emitcode ("rr", "a");
5550 l = aopGet (AOP (left), offset, FALSE, FALSE);
5552 emitcode ("rrc", "a");
5553 if (AOP_SIZE (result) > 1)
5554 aopPut (AOP (result), "a", offset--);
5556 /* now we need to put the carry into the
5557 highest order byte of the result */
5558 if (AOP_SIZE (result) > 1)
5560 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5563 emitcode ("mov", "acc.7,c");
5565 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5566 freeAsmop (left, NULL, ic, TRUE);
5567 freeAsmop (result, NULL, ic, TRUE);
5570 /*-----------------------------------------------------------------*/
5571 /* genRLC - generate code for rotate left with carry */
5572 /*-----------------------------------------------------------------*/
5576 operand *left, *result;
5577 int size, offset = 0;
5580 D(emitcode ("; genRLC",""));
5582 /* rotate right with carry */
5583 left = IC_LEFT (ic);
5584 result = IC_RESULT (ic);
5585 aopOp (left, ic, FALSE);
5586 aopOp (result, ic, FALSE);
5588 /* move it to the result */
5589 size = AOP_SIZE (result);
5593 l = aopGet (AOP (left), offset, FALSE, FALSE);
5595 if (size == 0) { /* special case for 1 byte */
5599 emitcode ("add", "a,acc");
5600 if (AOP_SIZE (result) > 1)
5601 aopPut (AOP (result), "a", offset++);
5604 l = aopGet (AOP (left), offset, FALSE, FALSE);
5606 emitcode ("rlc", "a");
5607 if (AOP_SIZE (result) > 1)
5608 aopPut (AOP (result), "a", offset++);
5611 /* now we need to put the carry into the
5612 highest order byte of the result */
5613 if (AOP_SIZE (result) > 1)
5615 l = aopGet (AOP (result), 0, FALSE, FALSE);
5618 emitcode ("mov", "acc.0,c");
5620 aopPut (AOP (result), "a", 0);
5621 freeAsmop (left, NULL, ic, TRUE);
5622 freeAsmop (result, NULL, ic, TRUE);
5625 /*-----------------------------------------------------------------*/
5626 /* genGetHbit - generates code get highest order bit */
5627 /*-----------------------------------------------------------------*/
5629 genGetHbit (iCode * ic)
5631 operand *left, *result;
5633 D(emitcode ("; genGetHbit",""));
5635 left = IC_LEFT (ic);
5636 result = IC_RESULT (ic);
5637 aopOp (left, ic, FALSE);
5638 aopOp (result, ic, FALSE);
5640 /* get the highest order byte into a */
5641 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5642 if (AOP_TYPE (result) == AOP_CRY)
5644 emitcode ("rlc", "a");
5649 emitcode ("rl", "a");
5650 emitcode ("anl", "a,#0x01");
5655 freeAsmop (left, NULL, ic, TRUE);
5656 freeAsmop (result, NULL, ic, TRUE);
5659 /*-----------------------------------------------------------------*/
5660 /* AccRol - rotate left accumulator by known count */
5661 /*-----------------------------------------------------------------*/
5663 AccRol (int shCount)
5665 shCount &= 0x0007; // shCount : 0..7
5672 emitcode ("rl", "a");
5675 emitcode ("rl", "a");
5676 emitcode ("rl", "a");
5679 emitcode ("swap", "a");
5680 emitcode ("rr", "a");
5683 emitcode ("swap", "a");
5686 emitcode ("swap", "a");
5687 emitcode ("rl", "a");
5690 emitcode ("rr", "a");
5691 emitcode ("rr", "a");
5694 emitcode ("rr", "a");
5699 /*-----------------------------------------------------------------*/
5700 /* AccLsh - left shift accumulator by known count */
5701 /*-----------------------------------------------------------------*/
5703 AccLsh (int shCount)
5708 emitcode ("add", "a,acc");
5709 else if (shCount == 2)
5711 emitcode ("add", "a,acc");
5712 emitcode ("add", "a,acc");
5716 /* rotate left accumulator */
5718 /* and kill the lower order bits */
5719 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5724 /*-----------------------------------------------------------------*/
5725 /* AccRsh - right shift accumulator by known count */
5726 /*-----------------------------------------------------------------*/
5728 AccRsh (int shCount)
5735 emitcode ("rrc", "a");
5739 /* rotate right accumulator */
5740 AccRol (8 - shCount);
5741 /* and kill the higher order bits */
5742 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5747 /*-----------------------------------------------------------------*/
5748 /* AccSRsh - signed right shift accumulator by known count */
5749 /*-----------------------------------------------------------------*/
5751 AccSRsh (int shCount)
5758 emitcode ("mov", "c,acc.7");
5759 emitcode ("rrc", "a");
5761 else if (shCount == 2)
5763 emitcode ("mov", "c,acc.7");
5764 emitcode ("rrc", "a");
5765 emitcode ("mov", "c,acc.7");
5766 emitcode ("rrc", "a");
5770 tlbl = newiTempLabel (NULL);
5771 /* rotate right accumulator */
5772 AccRol (8 - shCount);
5773 /* and kill the higher order bits */
5774 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5775 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5776 emitcode ("orl", "a,#0x%02x",
5777 (unsigned char) ~SRMask[shCount]);
5778 emitcode ("", "%05d$:", tlbl->key + 100);
5783 /*-----------------------------------------------------------------*/
5784 /* shiftR1Left2Result - shift right one byte from left to result */
5785 /*-----------------------------------------------------------------*/
5787 shiftR1Left2Result (operand * left, int offl,
5788 operand * result, int offr,
5789 int shCount, int sign)
5791 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5792 /* shift right accumulator */
5797 aopPut (AOP (result), "a", offr);
5800 /*-----------------------------------------------------------------*/
5801 /* shiftL1Left2Result - shift left one byte from left to result */
5802 /*-----------------------------------------------------------------*/
5804 shiftL1Left2Result (operand * left, int offl,
5805 operand * result, int offr, int shCount)
5808 l = aopGet (AOP (left), offl, FALSE, FALSE);
5810 /* shift left accumulator */
5812 aopPut (AOP (result), "a", offr);
5815 /*-----------------------------------------------------------------*/
5816 /* movLeft2Result - move byte from left to result */
5817 /*-----------------------------------------------------------------*/
5819 movLeft2Result (operand * left, int offl,
5820 operand * result, int offr, int sign)
5823 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5825 l = aopGet (AOP (left), offl, FALSE, FALSE);
5827 if (*l == '@' && (IS_AOP_PREG (result)))
5829 emitcode ("mov", "a,%s", l);
5830 aopPut (AOP (result), "a", offr);
5835 aopPut (AOP (result), l, offr);
5838 /* MSB sign in acc.7 ! */
5839 if (getDataSize (left) == offl + 1)
5841 emitcode ("mov", "a,%s", l);
5842 aopPut (AOP (result), "a", offr);
5849 /*-----------------------------------------------------------------*/
5850 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5851 /*-----------------------------------------------------------------*/
5855 emitcode ("rrc", "a");
5856 emitcode ("xch", "a,%s", x);
5857 emitcode ("rrc", "a");
5858 emitcode ("xch", "a,%s", x);
5861 /*-----------------------------------------------------------------*/
5862 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5863 /*-----------------------------------------------------------------*/
5867 emitcode ("xch", "a,%s", x);
5868 emitcode ("rlc", "a");
5869 emitcode ("xch", "a,%s", x);
5870 emitcode ("rlc", "a");
5873 /*-----------------------------------------------------------------*/
5874 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5875 /*-----------------------------------------------------------------*/
5879 emitcode ("xch", "a,%s", x);
5880 emitcode ("add", "a,acc");
5881 emitcode ("xch", "a,%s", x);
5882 emitcode ("rlc", "a");
5885 /*-----------------------------------------------------------------*/
5886 /* AccAXLsh - left shift a:x by known count (0..7) */
5887 /*-----------------------------------------------------------------*/
5889 AccAXLsh (char *x, int shCount)
5904 case 5: // AAAAABBB:CCCCCDDD
5906 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5908 emitcode ("anl", "a,#0x%02x",
5909 SLMask[shCount]); // BBB00000:CCCCCDDD
5911 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5913 AccRol (shCount); // DDDCCCCC:BBB00000
5915 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5917 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5919 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5921 emitcode ("anl", "a,#0x%02x",
5922 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5924 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5926 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5929 case 6: // AAAAAABB:CCCCCCDD
5930 emitcode ("anl", "a,#0x%02x",
5931 SRMask[shCount]); // 000000BB:CCCCCCDD
5932 emitcode ("mov", "c,acc.0"); // c = B
5933 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5935 AccAXRrl1 (x); // BCCCCCCD:D000000B
5936 AccAXRrl1 (x); // BBCCCCCC:DD000000
5938 emitcode("rrc","a");
5939 emitcode("xch","a,%s", x);
5940 emitcode("rrc","a");
5941 emitcode("mov","c,acc.0"); //<< get correct bit
5942 emitcode("xch","a,%s", x);
5944 emitcode("rrc","a");
5945 emitcode("xch","a,%s", x);
5946 emitcode("rrc","a");
5947 emitcode("xch","a,%s", x);
5950 case 7: // a:x <<= 7
5952 emitcode ("anl", "a,#0x%02x",
5953 SRMask[shCount]); // 0000000B:CCCCCCCD
5955 emitcode ("mov", "c,acc.0"); // c = B
5957 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5959 AccAXRrl1 (x); // BCCCCCCC:D0000000
5967 /*-----------------------------------------------------------------*/
5968 /* AccAXRsh - right shift a:x known count (0..7) */
5969 /*-----------------------------------------------------------------*/
5971 AccAXRsh (char *x, int shCount)
5979 AccAXRrl1 (x); // 0->a:x
5984 AccAXRrl1 (x); // 0->a:x
5987 AccAXRrl1 (x); // 0->a:x
5992 case 5: // AAAAABBB:CCCCCDDD = a:x
5994 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5996 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5998 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6000 emitcode ("anl", "a,#0x%02x",
6001 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6003 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6005 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6007 emitcode ("anl", "a,#0x%02x",
6008 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6010 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6012 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6014 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6017 case 6: // AABBBBBB:CCDDDDDD
6019 emitcode ("mov", "c,acc.7");
6020 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6022 emitcode ("mov", "c,acc.7");
6023 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6025 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6027 emitcode ("anl", "a,#0x%02x",
6028 SRMask[shCount]); // 000000AA:BBBBBBCC
6031 case 7: // ABBBBBBB:CDDDDDDD
6033 emitcode ("mov", "c,acc.7"); // c = A
6035 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6037 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6039 emitcode ("anl", "a,#0x%02x",
6040 SRMask[shCount]); // 0000000A:BBBBBBBC
6048 /*-----------------------------------------------------------------*/
6049 /* AccAXRshS - right shift signed a:x known count (0..7) */
6050 /*-----------------------------------------------------------------*/
6052 AccAXRshS (char *x, int shCount)
6060 emitcode ("mov", "c,acc.7");
6061 AccAXRrl1 (x); // s->a:x
6065 emitcode ("mov", "c,acc.7");
6066 AccAXRrl1 (x); // s->a:x
6068 emitcode ("mov", "c,acc.7");
6069 AccAXRrl1 (x); // s->a:x
6074 case 5: // AAAAABBB:CCCCCDDD = a:x
6076 tlbl = newiTempLabel (NULL);
6077 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6079 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6081 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6083 emitcode ("anl", "a,#0x%02x",
6084 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6086 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6088 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6090 emitcode ("anl", "a,#0x%02x",
6091 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6093 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6095 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6097 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6099 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6100 emitcode ("orl", "a,#0x%02x",
6101 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6103 emitcode ("", "%05d$:", tlbl->key + 100);
6104 break; // SSSSAAAA:BBBCCCCC
6106 case 6: // AABBBBBB:CCDDDDDD
6108 tlbl = newiTempLabel (NULL);
6109 emitcode ("mov", "c,acc.7");
6110 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6112 emitcode ("mov", "c,acc.7");
6113 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6115 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6117 emitcode ("anl", "a,#0x%02x",
6118 SRMask[shCount]); // 000000AA:BBBBBBCC
6120 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6121 emitcode ("orl", "a,#0x%02x",
6122 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6124 emitcode ("", "%05d$:", tlbl->key + 100);
6126 case 7: // ABBBBBBB:CDDDDDDD
6128 tlbl = newiTempLabel (NULL);
6129 emitcode ("mov", "c,acc.7"); // c = A
6131 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6133 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6135 emitcode ("anl", "a,#0x%02x",
6136 SRMask[shCount]); // 0000000A:BBBBBBBC
6138 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6139 emitcode ("orl", "a,#0x%02x",
6140 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6142 emitcode ("", "%05d$:", tlbl->key + 100);
6149 /*-----------------------------------------------------------------*/
6150 /* shiftL2Left2Result - shift left two bytes from left to result */
6151 /*-----------------------------------------------------------------*/
6153 shiftL2Left2Result (operand * left, int offl,
6154 operand * result, int offr, int shCount)
6156 if (sameRegs (AOP (result), AOP (left)) &&
6157 ((offl + MSB16) == offr))
6159 /* don't crash result[offr] */
6160 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6161 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6165 movLeft2Result (left, offl, result, offr, 0);
6166 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6168 /* ax << shCount (x = lsb(result)) */
6169 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6170 aopPut (AOP (result), "a", offr + MSB16);
6174 /*-----------------------------------------------------------------*/
6175 /* shiftR2Left2Result - shift right two bytes from left to result */
6176 /*-----------------------------------------------------------------*/
6178 shiftR2Left2Result (operand * left, int offl,
6179 operand * result, int offr,
6180 int shCount, int sign)
6182 if (sameRegs (AOP (result), AOP (left)) &&
6183 ((offl + MSB16) == offr))
6185 /* don't crash result[offr] */
6186 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6187 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6191 movLeft2Result (left, offl, result, offr, 0);
6192 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6194 /* a:x >> shCount (x = lsb(result)) */
6196 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6198 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6199 if (getDataSize (result) > 1)
6200 aopPut (AOP (result), "a", offr + MSB16);
6203 /*-----------------------------------------------------------------*/
6204 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6205 /*-----------------------------------------------------------------*/
6207 shiftLLeftOrResult (operand * left, int offl,
6208 operand * result, int offr, int shCount)
6210 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6211 /* shift left accumulator */
6213 /* or with result */
6214 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6215 /* back to result */
6216 aopPut (AOP (result), "a", offr);
6219 /*-----------------------------------------------------------------*/
6220 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6221 /*-----------------------------------------------------------------*/
6223 shiftRLeftOrResult (operand * left, int offl,
6224 operand * result, int offr, int shCount)
6226 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6227 /* shift right accumulator */
6229 /* or with result */
6230 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6231 /* back to result */
6232 aopPut (AOP (result), "a", offr);
6235 /*-----------------------------------------------------------------*/
6236 /* genlshOne - left shift a one byte quantity by known count */
6237 /*-----------------------------------------------------------------*/
6239 genlshOne (operand * result, operand * left, int shCount)
6241 D(emitcode ("; genlshOne",""));
6243 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6246 /*-----------------------------------------------------------------*/
6247 /* genlshTwo - left shift two bytes by known amount != 0 */
6248 /*-----------------------------------------------------------------*/
6250 genlshTwo (operand * result, operand * left, int shCount)
6254 D(emitcode ("; genlshTwo",""));
6256 size = getDataSize (result);
6258 /* if shCount >= 8 */
6266 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6268 movLeft2Result (left, LSB, result, MSB16, 0);
6270 aopPut (AOP (result), zero, LSB);
6273 /* 1 <= shCount <= 7 */
6277 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6279 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6283 /*-----------------------------------------------------------------*/
6284 /* shiftLLong - shift left one long from left to result */
6285 /* offl = LSB or MSB16 */
6286 /*-----------------------------------------------------------------*/
6288 shiftLLong (operand * left, operand * result, int offr)
6291 int size = AOP_SIZE (result);
6293 if (size >= LSB + offr)
6295 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6297 emitcode ("add", "a,acc");
6298 if (sameRegs (AOP (left), AOP (result)) &&
6299 size >= MSB16 + offr && offr != LSB)
6300 emitcode ("xch", "a,%s",
6301 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6303 aopPut (AOP (result), "a", LSB + offr);
6306 if (size >= MSB16 + offr)
6308 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6310 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6313 emitcode ("rlc", "a");
6314 if (sameRegs (AOP (left), AOP (result)) &&
6315 size >= MSB24 + offr && offr != LSB)
6316 emitcode ("xch", "a,%s",
6317 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6319 aopPut (AOP (result), "a", MSB16 + offr);
6322 if (size >= MSB24 + offr)
6324 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6326 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6329 emitcode ("rlc", "a");
6330 if (sameRegs (AOP (left), AOP (result)) &&
6331 size >= MSB32 + offr && offr != LSB)
6332 emitcode ("xch", "a,%s",
6333 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6335 aopPut (AOP (result), "a", MSB24 + offr);
6338 if (size > MSB32 + offr)
6340 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6342 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6345 emitcode ("rlc", "a");
6346 aopPut (AOP (result), "a", MSB32 + offr);
6349 aopPut (AOP (result), zero, LSB);
6352 /*-----------------------------------------------------------------*/
6353 /* genlshFour - shift four byte by a known amount != 0 */
6354 /*-----------------------------------------------------------------*/
6356 genlshFour (operand * result, operand * left, int shCount)
6360 D(emitcode ("; genlshFour",""));
6362 size = AOP_SIZE (result);
6364 /* if shifting more that 3 bytes */
6369 /* lowest order of left goes to the highest
6370 order of the destination */
6371 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6373 movLeft2Result (left, LSB, result, MSB32, 0);
6374 aopPut (AOP (result), zero, LSB);
6375 aopPut (AOP (result), zero, MSB16);
6376 aopPut (AOP (result), zero, MSB24);
6380 /* more than two bytes */
6381 else if (shCount >= 16)
6383 /* lower order two bytes goes to higher order two bytes */
6385 /* if some more remaining */
6387 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6390 movLeft2Result (left, MSB16, result, MSB32, 0);
6391 movLeft2Result (left, LSB, result, MSB24, 0);
6393 aopPut (AOP (result), zero, MSB16);
6394 aopPut (AOP (result), zero, LSB);
6398 /* if more than 1 byte */
6399 else if (shCount >= 8)
6401 /* lower order three bytes goes to higher order three bytes */
6406 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6408 movLeft2Result (left, LSB, result, MSB16, 0);
6414 movLeft2Result (left, MSB24, result, MSB32, 0);
6415 movLeft2Result (left, MSB16, result, MSB24, 0);
6416 movLeft2Result (left, LSB, result, MSB16, 0);
6417 aopPut (AOP (result), zero, LSB);
6419 else if (shCount == 1)
6420 shiftLLong (left, result, MSB16);
6423 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6424 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6425 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6426 aopPut (AOP (result), zero, LSB);
6431 /* 1 <= shCount <= 7 */
6432 else if (shCount <= 2)
6434 shiftLLong (left, result, LSB);
6436 shiftLLong (result, result, LSB);
6438 /* 3 <= shCount <= 7, optimize */
6441 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6442 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6443 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6447 /*-----------------------------------------------------------------*/
6448 /* genLeftShiftLiteral - left shifting by known count */
6449 /*-----------------------------------------------------------------*/
6451 genLeftShiftLiteral (operand * left,
6456 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6459 D(emitcode ("; genLeftShiftLiteral",""));
6461 freeAsmop (right, NULL, ic, TRUE);
6463 aopOp (left, ic, FALSE);
6464 aopOp (result, ic, FALSE);
6466 size = getSize (operandType (result));
6469 emitcode ("; shift left ", "result %d, left %d", size,
6473 /* I suppose that the left size >= result size */
6478 movLeft2Result (left, size, result, size, 0);
6482 else if (shCount >= (size * 8))
6484 aopPut (AOP (result), zero, size);
6490 genlshOne (result, left, shCount);
6494 genlshTwo (result, left, shCount);
6498 genlshFour (result, left, shCount);
6501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6502 "*** ack! mystery literal shift!\n");
6506 freeAsmop (left, NULL, ic, TRUE);
6507 freeAsmop (result, NULL, ic, TRUE);
6510 /*-----------------------------------------------------------------*/
6511 /* genLeftShift - generates code for left shifting */
6512 /*-----------------------------------------------------------------*/
6514 genLeftShift (iCode * ic)
6516 operand *left, *right, *result;
6519 symbol *tlbl, *tlbl1;
6521 D(emitcode ("; genLeftShift",""));
6523 right = IC_RIGHT (ic);
6524 left = IC_LEFT (ic);
6525 result = IC_RESULT (ic);
6527 aopOp (right, ic, FALSE);
6529 /* if the shift count is known then do it
6530 as efficiently as possible */
6531 if (AOP_TYPE (right) == AOP_LIT)
6533 genLeftShiftLiteral (left, right, result, ic);
6537 /* shift count is unknown then we have to form
6538 a loop get the loop count in B : Note: we take
6539 only the lower order byte since shifting
6540 more that 32 bits make no sense anyway, ( the
6541 largest size of an object can be only 32 bits ) */
6543 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6544 emitcode ("inc", "b");
6545 freeAsmop (right, NULL, ic, TRUE);
6546 aopOp (left, ic, FALSE);
6547 aopOp (result, ic, FALSE);
6549 /* now move the left to the result if they are not the
6551 if (!sameRegs (AOP (left), AOP (result)) &&
6552 AOP_SIZE (result) > 1)
6555 size = AOP_SIZE (result);
6559 l = aopGet (AOP (left), offset, FALSE, TRUE);
6560 if (*l == '@' && (IS_AOP_PREG (result)))
6563 emitcode ("mov", "a,%s", l);
6564 aopPut (AOP (result), "a", offset);
6567 aopPut (AOP (result), l, offset);
6572 tlbl = newiTempLabel (NULL);
6573 size = AOP_SIZE (result);
6575 tlbl1 = newiTempLabel (NULL);
6577 /* if it is only one byte then */
6580 symbol *tlbl1 = newiTempLabel (NULL);
6582 l = aopGet (AOP (left), 0, FALSE, FALSE);
6584 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6585 emitcode ("", "%05d$:", tlbl->key + 100);
6586 emitcode ("add", "a,acc");
6587 emitcode ("", "%05d$:", tlbl1->key + 100);
6588 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6589 aopPut (AOP (result), "a", 0);
6593 reAdjustPreg (AOP (result));
6595 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6596 emitcode ("", "%05d$:", tlbl->key + 100);
6597 l = aopGet (AOP (result), offset, FALSE, FALSE);
6599 emitcode ("add", "a,acc");
6600 aopPut (AOP (result), "a", offset++);
6603 l = aopGet (AOP (result), offset, FALSE, FALSE);
6605 emitcode ("rlc", "a");
6606 aopPut (AOP (result), "a", offset++);
6608 reAdjustPreg (AOP (result));
6610 emitcode ("", "%05d$:", tlbl1->key + 100);
6611 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6613 freeAsmop (left, NULL, ic, TRUE);
6614 freeAsmop (result, NULL, ic, TRUE);
6617 /*-----------------------------------------------------------------*/
6618 /* genrshOne - right shift a one byte quantity by known count */
6619 /*-----------------------------------------------------------------*/
6621 genrshOne (operand * result, operand * left,
6622 int shCount, int sign)
6624 D(emitcode ("; genrshOne",""));
6626 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6629 /*-----------------------------------------------------------------*/
6630 /* genrshTwo - right shift two bytes by known amount != 0 */
6631 /*-----------------------------------------------------------------*/
6633 genrshTwo (operand * result, operand * left,
6634 int shCount, int sign)
6636 D(emitcode ("; genrshTwo",""));
6638 /* if shCount >= 8 */
6643 shiftR1Left2Result (left, MSB16, result, LSB,
6646 movLeft2Result (left, MSB16, result, LSB, sign);
6647 addSign (result, MSB16, sign);
6650 /* 1 <= shCount <= 7 */
6652 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6655 /*-----------------------------------------------------------------*/
6656 /* shiftRLong - shift right one long from left to result */
6657 /* offl = LSB or MSB16 */
6658 /*-----------------------------------------------------------------*/
6660 shiftRLong (operand * left, int offl,
6661 operand * result, int sign)
6663 int isSameRegs=sameRegs(AOP(left),AOP(result));
6665 if (isSameRegs && offl>1) {
6666 // we are in big trouble, but this shouldn't happen
6667 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6670 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6675 emitcode ("rlc", "a");
6676 emitcode ("subb", "a,acc");
6678 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6680 aopPut (AOP (result), "a", MSB32);
6681 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6684 aopPut (AOP(result), zero, MSB32);
6689 emitcode ("clr", "c");
6691 emitcode ("mov", "c,acc.7");
6694 emitcode ("rrc", "a");
6696 if (isSameRegs && offl==MSB16) {
6697 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6699 aopPut (AOP (result), "a", MSB32-offl);
6700 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6703 emitcode ("rrc", "a");
6704 if (isSameRegs && offl==1) {
6705 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6707 aopPut (AOP (result), "a", MSB24-offl);
6708 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6710 emitcode ("rrc", "a");
6711 aopPut (AOP (result), "a", MSB16 - offl);
6715 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6716 emitcode ("rrc", "a");
6717 aopPut (AOP (result), "a", LSB);
6721 /*-----------------------------------------------------------------*/
6722 /* genrshFour - shift four byte by a known amount != 0 */
6723 /*-----------------------------------------------------------------*/
6725 genrshFour (operand * result, operand * left,
6726 int shCount, int sign)
6728 D(emitcode ("; genrshFour",""));
6730 /* if shifting more that 3 bytes */
6735 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6737 movLeft2Result (left, MSB32, result, LSB, sign);
6738 addSign (result, MSB16, sign);
6740 else if (shCount >= 16)
6744 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6747 movLeft2Result (left, MSB24, result, LSB, 0);
6748 movLeft2Result (left, MSB32, result, MSB16, sign);
6750 addSign (result, MSB24, sign);
6752 else if (shCount >= 8)
6756 shiftRLong (left, MSB16, result, sign);
6757 else if (shCount == 0)
6759 movLeft2Result (left, MSB16, result, LSB, 0);
6760 movLeft2Result (left, MSB24, result, MSB16, 0);
6761 movLeft2Result (left, MSB32, result, MSB24, sign);
6762 addSign (result, MSB32, sign);
6766 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6767 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6768 /* the last shift is signed */
6769 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6770 addSign (result, MSB32, sign);
6774 { /* 1 <= shCount <= 7 */
6777 shiftRLong (left, LSB, result, sign);
6779 shiftRLong (result, LSB, result, sign);
6783 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6784 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6785 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6790 /*-----------------------------------------------------------------*/
6791 /* genRightShiftLiteral - right shifting by known count */
6792 /*-----------------------------------------------------------------*/
6794 genRightShiftLiteral (operand * left,
6800 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6803 D(emitcode ("; genRightShiftLiteral",""));
6805 freeAsmop (right, NULL, ic, TRUE);
6807 aopOp (left, ic, FALSE);
6808 aopOp (result, ic, FALSE);
6811 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6815 size = getDataSize (left);
6816 /* test the LEFT size !!! */
6818 /* I suppose that the left size >= result size */
6821 size = getDataSize (result);
6823 movLeft2Result (left, size, result, size, 0);
6826 else if (shCount >= (size * 8))
6829 /* get sign in acc.7 */
6830 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);
6857 /*-----------------------------------------------------------------*/
6858 /* genSignedRightShift - right shift of signed number */
6859 /*-----------------------------------------------------------------*/
6861 genSignedRightShift (iCode * ic)
6863 operand *right, *left, *result;
6866 symbol *tlbl, *tlbl1;
6868 D(emitcode ("; genSignedRightShift",""));
6870 /* we do it the hard way put the shift count in b
6871 and loop thru preserving the sign */
6873 right = IC_RIGHT (ic);
6874 left = IC_LEFT (ic);
6875 result = IC_RESULT (ic);
6877 aopOp (right, ic, FALSE);
6880 if (AOP_TYPE (right) == AOP_LIT)
6882 genRightShiftLiteral (left, right, result, ic, 1);
6885 /* shift count is unknown then we have to form
6886 a loop get the loop count in B : Note: we take
6887 only the lower order byte since shifting
6888 more that 32 bits make no sense anyway, ( the
6889 largest size of an object can be only 32 bits ) */
6891 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6892 emitcode ("inc", "b");
6893 freeAsmop (right, NULL, ic, TRUE);
6894 aopOp (left, ic, FALSE);
6895 aopOp (result, ic, FALSE);
6897 /* now move the left to the result if they are not the
6899 if (!sameRegs (AOP (left), AOP (result)) &&
6900 AOP_SIZE (result) > 1)
6903 size = AOP_SIZE (result);
6907 l = aopGet (AOP (left), offset, FALSE, TRUE);
6908 if (*l == '@' && IS_AOP_PREG (result))
6911 emitcode ("mov", "a,%s", l);
6912 aopPut (AOP (result), "a", offset);
6915 aopPut (AOP (result), l, offset);
6920 /* mov the highest order bit to OVR */
6921 tlbl = newiTempLabel (NULL);
6922 tlbl1 = newiTempLabel (NULL);
6924 size = AOP_SIZE (result);
6926 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6927 emitcode ("rlc", "a");
6928 emitcode ("mov", "ov,c");
6929 /* if it is only one byte then */
6932 l = aopGet (AOP (left), 0, FALSE, FALSE);
6934 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6935 emitcode ("", "%05d$:", tlbl->key + 100);
6936 emitcode ("mov", "c,ov");
6937 emitcode ("rrc", "a");
6938 emitcode ("", "%05d$:", tlbl1->key + 100);
6939 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6940 aopPut (AOP (result), "a", 0);
6944 reAdjustPreg (AOP (result));
6945 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6946 emitcode ("", "%05d$:", tlbl->key + 100);
6947 emitcode ("mov", "c,ov");
6950 l = aopGet (AOP (result), offset, FALSE, FALSE);
6952 emitcode ("rrc", "a");
6953 aopPut (AOP (result), "a", offset--);
6955 reAdjustPreg (AOP (result));
6956 emitcode ("", "%05d$:", tlbl1->key + 100);
6957 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6960 freeAsmop (left, NULL, ic, TRUE);
6961 freeAsmop (result, NULL, ic, TRUE);
6964 /*-----------------------------------------------------------------*/
6965 /* genRightShift - generate code for right shifting */
6966 /*-----------------------------------------------------------------*/
6968 genRightShift (iCode * ic)
6970 operand *right, *left, *result;
6974 symbol *tlbl, *tlbl1;
6976 D(emitcode ("; genRightShift",""));
6978 /* if signed then we do it the hard way preserve the
6979 sign bit moving it inwards */
6980 retype = getSpec (operandType (IC_RESULT (ic)));
6982 if (!SPEC_USIGN (retype))
6984 genSignedRightShift (ic);
6988 /* signed & unsigned types are treated the same : i.e. the
6989 signed is NOT propagated inwards : quoting from the
6990 ANSI - standard : "for E1 >> E2, is equivalent to division
6991 by 2**E2 if unsigned or if it has a non-negative value,
6992 otherwise the result is implementation defined ", MY definition
6993 is that the sign does not get propagated */
6995 right = IC_RIGHT (ic);
6996 left = IC_LEFT (ic);
6997 result = IC_RESULT (ic);
6999 aopOp (right, ic, FALSE);
7001 /* if the shift count is known then do it
7002 as efficiently as possible */
7003 if (AOP_TYPE (right) == AOP_LIT)
7005 genRightShiftLiteral (left, right, result, ic, 0);
7009 /* shift count is unknown then we have to form
7010 a loop get the loop count in B : Note: we take
7011 only the lower order byte since shifting
7012 more that 32 bits make no sense anyway, ( the
7013 largest size of an object can be only 32 bits ) */
7015 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7016 emitcode ("inc", "b");
7017 freeAsmop (right, NULL, ic, TRUE);
7018 aopOp (left, ic, FALSE);
7019 aopOp (result, ic, FALSE);
7021 /* now move the left to the result if they are not the
7023 if (!sameRegs (AOP (left), AOP (result)) &&
7024 AOP_SIZE (result) > 1)
7027 size = AOP_SIZE (result);
7031 l = aopGet (AOP (left), offset, FALSE, TRUE);
7032 if (*l == '@' && IS_AOP_PREG (result))
7035 emitcode ("mov", "a,%s", l);
7036 aopPut (AOP (result), "a", offset);
7039 aopPut (AOP (result), l, offset);
7044 tlbl = newiTempLabel (NULL);
7045 tlbl1 = newiTempLabel (NULL);
7046 size = AOP_SIZE (result);
7049 /* if it is only one byte then */
7052 l = aopGet (AOP (left), 0, FALSE, FALSE);
7054 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7055 emitcode ("", "%05d$:", tlbl->key + 100);
7057 emitcode ("rrc", "a");
7058 emitcode ("", "%05d$:", tlbl1->key + 100);
7059 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7060 aopPut (AOP (result), "a", 0);
7064 reAdjustPreg (AOP (result));
7065 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7066 emitcode ("", "%05d$:", tlbl->key + 100);
7070 l = aopGet (AOP (result), offset, FALSE, FALSE);
7072 emitcode ("rrc", "a");
7073 aopPut (AOP (result), "a", offset--);
7075 reAdjustPreg (AOP (result));
7077 emitcode ("", "%05d$:", tlbl1->key + 100);
7078 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7081 freeAsmop (left, NULL, ic, TRUE);
7082 freeAsmop (result, NULL, ic, TRUE);
7085 /*-----------------------------------------------------------------*/
7086 /* genUnpackBits - generates code for unpacking bits */
7087 /*-----------------------------------------------------------------*/
7089 genUnpackBits (operand * result, char *rname, int ptype)
7097 D(emitcode ("; genUnpackBits",""));
7099 etype = getSpec (operandType (result));
7100 rsize = getSize (operandType (result));
7101 /* read the first byte */
7107 emitcode ("mov", "a,@%s", rname);
7111 emitcode ("movx", "a,@%s", rname);
7115 emitcode ("movx", "a,@dptr");
7119 emitcode ("clr", "a");
7120 emitcode ("movc", "a,@a+dptr");
7124 emitcode ("lcall", "__gptrget");
7128 rlen = SPEC_BLEN (etype);
7130 /* if we have bitdisplacement then it fits */
7131 /* into this byte completely or if length is */
7132 /* less than a byte */
7133 if ((shCnt = SPEC_BSTR (etype)) ||
7134 (SPEC_BLEN (etype) <= 8))
7137 /* shift right acc */
7140 emitcode ("anl", "a,#0x%02x",
7141 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7142 aopPut (AOP (result), "a", offset++);
7146 /* bit field did not fit in a byte */
7147 aopPut (AOP (result), "a", offset++);
7156 emitcode ("inc", "%s", rname);
7157 emitcode ("mov", "a,@%s", rname);
7161 emitcode ("inc", "%s", rname);
7162 emitcode ("movx", "a,@%s", rname);
7166 emitcode ("inc", "dptr");
7167 emitcode ("movx", "a,@dptr");
7171 emitcode ("clr", "a");
7172 emitcode ("inc", "dptr");
7173 emitcode ("movc", "a,@a+dptr");
7177 emitcode ("inc", "dptr");
7178 emitcode ("lcall", "__gptrget");
7183 /* if we are done */
7187 aopPut (AOP (result), "a", offset++);
7193 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7195 aopPut (AOP (result), "a", offset++);
7203 aopPut (AOP (result), zero, offset++);
7209 /*-----------------------------------------------------------------*/
7210 /* genDataPointerGet - generates code when ptr offset is known */
7211 /*-----------------------------------------------------------------*/
7213 genDataPointerGet (operand * left,
7219 int size, offset = 0;
7221 D(emitcode ("; genDataPointerGet",""));
7223 aopOp (result, ic, TRUE);
7225 /* get the string representation of the name */
7226 l = aopGet (AOP (left), 0, FALSE, TRUE);
7227 size = AOP_SIZE (result);
7231 sprintf (buffer, "(%s + %d)", l + 1, offset);
7233 sprintf (buffer, "%s", l + 1);
7234 aopPut (AOP (result), buffer, offset++);
7237 freeAsmop (left, NULL, ic, TRUE);
7238 freeAsmop (result, NULL, ic, TRUE);
7241 /*-----------------------------------------------------------------*/
7242 /* genNearPointerGet - emitcode for near pointer fetch */
7243 /*-----------------------------------------------------------------*/
7245 genNearPointerGet (operand * left,
7253 sym_link *rtype, *retype;
7254 sym_link *ltype = operandType (left);
7257 D(emitcode ("; genNearPointerGet",""));
7259 rtype = operandType (result);
7260 retype = getSpec (rtype);
7262 aopOp (left, ic, FALSE);
7264 /* if left is rematerialisable and
7265 result is not bit variable type and
7266 the left is pointer to data space i.e
7267 lower 128 bytes of space */
7268 if (AOP_TYPE (left) == AOP_IMMD &&
7269 !IS_BITVAR (retype) &&
7270 DCL_TYPE (ltype) == POINTER)
7272 genDataPointerGet (left, result, ic);
7276 /* if the value is already in a pointer register
7277 then don't need anything more */
7278 if (!AOP_INPREG (AOP (left)))
7280 /* otherwise get a free pointer register */
7282 preg = getFreePtr (ic, &aop, FALSE);
7283 emitcode ("mov", "%s,%s",
7285 aopGet (AOP (left), 0, FALSE, TRUE));
7289 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7291 //aopOp (result, ic, FALSE);
7292 aopOp (result, ic, result?TRUE:FALSE);
7294 /* if bitfield then unpack the bits */
7295 if (IS_BITVAR (retype))
7296 genUnpackBits (result, rname, POINTER);
7299 /* we have can just get the values */
7300 int size = AOP_SIZE (result);
7305 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7308 emitcode ("mov", "a,@%s", rname);
7309 aopPut (AOP (result), "a", offset);
7313 sprintf (buffer, "@%s", rname);
7314 aopPut (AOP (result), buffer, offset);
7318 emitcode ("inc", "%s", rname);
7322 /* now some housekeeping stuff */
7323 if (aop) /* we had to allocate for this iCode */
7325 if (pi) { /* post increment present */
7326 aopPut(AOP ( left ),rname,0);
7328 freeAsmop (NULL, aop, ic, TRUE);
7332 /* we did not allocate which means left
7333 already in a pointer register, then
7334 if size > 0 && this could be used again
7335 we have to point it back to where it
7337 if ((AOP_SIZE (result) > 1 &&
7338 !OP_SYMBOL (left)->remat &&
7339 (OP_SYMBOL (left)->liveTo > ic->seq ||
7343 int size = AOP_SIZE (result) - 1;
7345 emitcode ("dec", "%s", rname);
7350 freeAsmop (left, NULL, ic, TRUE);
7351 freeAsmop (result, NULL, ic, TRUE);
7352 if (pi) pi->generated = 1;
7355 /*-----------------------------------------------------------------*/
7356 /* genPagedPointerGet - emitcode for paged pointer fetch */
7357 /*-----------------------------------------------------------------*/
7359 genPagedPointerGet (operand * left,
7367 sym_link *rtype, *retype;
7369 D(emitcode ("; genPagedPointerGet",""));
7371 rtype = operandType (result);
7372 retype = getSpec (rtype);
7374 aopOp (left, ic, FALSE);
7376 /* if the value is already in a pointer register
7377 then don't need anything more */
7378 if (!AOP_INPREG (AOP (left)))
7380 /* otherwise get a free pointer register */
7382 preg = getFreePtr (ic, &aop, FALSE);
7383 emitcode ("mov", "%s,%s",
7385 aopGet (AOP (left), 0, FALSE, TRUE));
7389 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7391 aopOp (result, ic, FALSE);
7393 /* if bitfield then unpack the bits */
7394 if (IS_BITVAR (retype))
7395 genUnpackBits (result, rname, PPOINTER);
7398 /* we have can just get the values */
7399 int size = AOP_SIZE (result);
7405 emitcode ("movx", "a,@%s", rname);
7406 aopPut (AOP (result), "a", offset);
7411 emitcode ("inc", "%s", rname);
7415 /* now some housekeeping stuff */
7416 if (aop) /* we had to allocate for this iCode */
7418 if (pi) aopPut ( AOP (left), rname, 0);
7419 freeAsmop (NULL, aop, ic, TRUE);
7423 /* we did not allocate which means left
7424 already in a pointer register, then
7425 if size > 0 && this could be used again
7426 we have to point it back to where it
7428 if ((AOP_SIZE (result) > 1 &&
7429 !OP_SYMBOL (left)->remat &&
7430 (OP_SYMBOL (left)->liveTo > ic->seq ||
7434 int size = AOP_SIZE (result) - 1;
7436 emitcode ("dec", "%s", rname);
7441 freeAsmop (left, NULL, ic, TRUE);
7442 freeAsmop (result, NULL, ic, TRUE);
7443 if (pi) pi->generated = 1;
7447 /*-----------------------------------------------------------------*/
7448 /* genFarPointerGet - gget value from far space */
7449 /*-----------------------------------------------------------------*/
7451 genFarPointerGet (operand * left,
7452 operand * result, iCode * ic, iCode * pi)
7455 sym_link *retype = getSpec (operandType (result));
7457 D(emitcode ("; genFarPointerGet",""));
7459 aopOp (left, ic, FALSE);
7461 /* if the operand is already in dptr
7462 then we do nothing else we move the value to dptr */
7463 if (AOP_TYPE (left) != AOP_STR)
7465 /* if this is remateriazable */
7466 if (AOP_TYPE (left) == AOP_IMMD)
7467 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7469 { /* we need to get it byte by byte */
7470 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7471 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7474 /* so dptr know contains the address */
7475 aopOp (result, ic, FALSE);
7477 /* if bit then unpack */
7478 if (IS_BITVAR (retype))
7479 genUnpackBits (result, "dptr", FPOINTER);
7482 size = AOP_SIZE (result);
7487 emitcode ("movx", "a,@dptr");
7488 aopPut (AOP (result), "a", offset++);
7490 emitcode ("inc", "dptr");
7494 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7495 aopPut ( AOP (left), "dpl", 0);
7496 aopPut ( AOP (left), "dph", 1);
7499 freeAsmop (left, NULL, ic, TRUE);
7500 freeAsmop (result, NULL, ic, TRUE);
7503 /*-----------------------------------------------------------------*/
7504 /* genCodePointerGet - gget value from code space */
7505 /*-----------------------------------------------------------------*/
7507 genCodePointerGet (operand * left,
7508 operand * result, iCode * ic, iCode *pi)
7511 sym_link *retype = getSpec (operandType (result));
7513 D(emitcode ("; genCodePointerGet",""));
7515 aopOp (left, ic, FALSE);
7517 /* if the operand is already in dptr
7518 then we do nothing else we move the value to dptr */
7519 if (AOP_TYPE (left) != AOP_STR)
7521 /* if this is remateriazable */
7522 if (AOP_TYPE (left) == AOP_IMMD)
7523 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7525 { /* we need to get it byte by byte */
7526 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7527 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7530 /* so dptr know contains the address */
7531 aopOp (result, ic, FALSE);
7533 /* if bit then unpack */
7534 if (IS_BITVAR (retype))
7535 genUnpackBits (result, "dptr", CPOINTER);
7538 size = AOP_SIZE (result);
7543 emitcode ("clr", "a");
7544 emitcode ("movc", "a,@a+dptr");
7545 aopPut (AOP (result), "a", offset++);
7547 emitcode ("inc", "dptr");
7551 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7552 aopPut ( AOP (left), "dpl", 0);
7553 aopPut ( AOP (left), "dph", 1);
7556 freeAsmop (left, NULL, ic, TRUE);
7557 freeAsmop (result, NULL, ic, TRUE);
7560 /*-----------------------------------------------------------------*/
7561 /* genGenPointerGet - gget value from generic pointer space */
7562 /*-----------------------------------------------------------------*/
7564 genGenPointerGet (operand * left,
7565 operand * result, iCode * ic, iCode *pi)
7568 sym_link *retype = getSpec (operandType (result));
7570 D(emitcode ("; genGenPointerGet",""));
7572 aopOp (left, ic, FALSE);
7574 /* if the operand is already in dptr
7575 then we do nothing else we move the value to dptr */
7576 if (AOP_TYPE (left) != AOP_STR)
7578 /* if this is remateriazable */
7579 if (AOP_TYPE (left) == AOP_IMMD)
7581 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7582 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7583 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7585 emitcode ("mov", "b,#%d", pointerCode (retype));
7588 { /* we need to get it byte by byte */
7589 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7590 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7591 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7594 /* so dptr know contains the address */
7595 aopOp (result, ic, FALSE);
7597 /* if bit then unpack */
7598 if (IS_BITVAR (retype))
7599 genUnpackBits (result, "dptr", GPOINTER);
7602 size = AOP_SIZE (result);
7607 emitcode ("lcall", "__gptrget");
7608 aopPut (AOP (result), "a", offset++);
7610 emitcode ("inc", "dptr");
7614 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7615 aopPut ( AOP (left), "dpl", 0);
7616 aopPut ( AOP (left), "dph", 1);
7617 aopPut ( AOP (left), "b", 2);
7620 freeAsmop (left, NULL, ic, TRUE);
7621 freeAsmop (result, NULL, ic, TRUE);
7624 /*-----------------------------------------------------------------*/
7625 /* genPointerGet - generate code for pointer get */
7626 /*-----------------------------------------------------------------*/
7628 genPointerGet (iCode * ic, iCode *pi)
7630 operand *left, *result;
7631 sym_link *type, *etype;
7634 D(emitcode ("; genPointerGet",""));
7636 left = IC_LEFT (ic);
7637 result = IC_RESULT (ic);
7639 /* depending on the type of pointer we need to
7640 move it to the correct pointer register */
7641 type = operandType (left);
7642 etype = getSpec (type);
7643 /* if left is of type of pointer then it is simple */
7644 if (IS_PTR (type) && !IS_FUNC (type->next))
7645 p_type = DCL_TYPE (type);
7648 /* we have to go by the storage class */
7649 p_type = PTR_TYPE (SPEC_OCLS (etype));
7652 /* special case when cast remat */
7653 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7654 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7655 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7656 type = operandType (left);
7657 p_type = DCL_TYPE (type);
7659 /* now that we have the pointer type we assign
7660 the pointer values */
7666 genNearPointerGet (left, result, ic, pi);
7670 genPagedPointerGet (left, result, ic, pi);
7674 genFarPointerGet (left, result, ic, pi);
7678 genCodePointerGet (left, result, ic, pi);
7682 genGenPointerGet (left, result, ic, pi);
7688 /*-----------------------------------------------------------------*/
7689 /* genPackBits - generates code for packed bit storage */
7690 /*-----------------------------------------------------------------*/
7692 genPackBits (sym_link * etype,
7694 char *rname, int p_type)
7702 D(emitcode ("; genPackBits",""));
7704 blen = SPEC_BLEN (etype);
7705 bstr = SPEC_BSTR (etype);
7707 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7710 /* if the bit lenth is less than or */
7711 /* it exactly fits a byte then */
7712 if (SPEC_BLEN (etype) <= 8)
7714 shCount = SPEC_BSTR (etype);
7716 /* shift left acc */
7719 if (SPEC_BLEN (etype) < 8)
7720 { /* if smaller than a byte */
7726 emitcode ("mov", "b,a");
7727 emitcode ("mov", "a,@%s", rname);
7731 emitcode ("mov", "b,a");
7732 emitcode ("movx", "a,@dptr");
7736 emitcode ("push", "b");
7737 emitcode ("push", "acc");
7738 emitcode ("lcall", "__gptrget");
7739 emitcode ("pop", "b");
7743 emitcode ("anl", "a,#0x%02x", (unsigned char)
7744 ((unsigned char) (0xFF << (blen + bstr)) |
7745 (unsigned char) (0xFF >> (8 - bstr))));
7746 emitcode ("orl", "a,b");
7747 if (p_type == GPOINTER)
7748 emitcode ("pop", "b");
7755 emitcode ("mov", "@%s,a", rname);
7759 emitcode ("movx", "@dptr,a");
7763 emitcode ("lcall", "__gptrput");
7768 if (SPEC_BLEN (etype) <= 8)
7771 emitcode ("inc", "%s", rname);
7772 rLen = SPEC_BLEN (etype);
7774 /* now generate for lengths greater than one byte */
7778 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7790 emitcode ("mov", "@%s,a", rname);
7793 emitcode ("mov", "@%s,%s", rname, l);
7798 emitcode ("movx", "@dptr,a");
7803 emitcode ("lcall", "__gptrput");
7806 emitcode ("inc", "%s", rname);
7811 /* last last was not complete */
7814 /* save the byte & read byte */
7818 emitcode ("mov", "b,a");
7819 emitcode ("mov", "a,@%s", rname);
7823 emitcode ("mov", "b,a");
7824 emitcode ("movx", "a,@dptr");
7828 emitcode ("push", "b");
7829 emitcode ("push", "acc");
7830 emitcode ("lcall", "__gptrget");
7831 emitcode ("pop", "b");
7835 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7836 emitcode ("orl", "a,b");
7839 if (p_type == GPOINTER)
7840 emitcode ("pop", "b");
7846 emitcode ("mov", "@%s,a", rname);
7850 emitcode ("movx", "@dptr,a");
7854 emitcode ("lcall", "__gptrput");
7858 /*-----------------------------------------------------------------*/
7859 /* genDataPointerSet - remat pointer to data space */
7860 /*-----------------------------------------------------------------*/
7862 genDataPointerSet (operand * right,
7866 int size, offset = 0;
7867 char *l, buffer[256];
7869 D(emitcode ("; genDataPointerSet",""));
7871 aopOp (right, ic, FALSE);
7873 l = aopGet (AOP (result), 0, FALSE, TRUE);
7874 size = AOP_SIZE (right);
7878 sprintf (buffer, "(%s + %d)", l + 1, offset);
7880 sprintf (buffer, "%s", l + 1);
7881 emitcode ("mov", "%s,%s", buffer,
7882 aopGet (AOP (right), offset++, FALSE, FALSE));
7885 freeAsmop (right, NULL, ic, TRUE);
7886 freeAsmop (result, NULL, ic, TRUE);
7889 /*-----------------------------------------------------------------*/
7890 /* genNearPointerSet - emitcode for near pointer put */
7891 /*-----------------------------------------------------------------*/
7893 genNearPointerSet (operand * right,
7901 sym_link *retype, *letype;
7902 sym_link *ptype = operandType (result);
7904 D(emitcode ("; genNearPointerSet",""));
7906 retype = getSpec (operandType (right));
7907 letype = getSpec (ptype);
7908 aopOp (result, ic, FALSE);
7910 /* if the result is rematerializable &
7911 in data space & not a bit variable */
7912 if (AOP_TYPE (result) == AOP_IMMD &&
7913 DCL_TYPE (ptype) == POINTER &&
7914 !IS_BITVAR (retype) &&
7915 !IS_BITVAR (letype))
7917 genDataPointerSet (right, result, ic);
7921 /* if the value is already in a pointer register
7922 then don't need anything more */
7923 if (!AOP_INPREG (AOP (result)))
7926 //AOP_TYPE (result) == AOP_STK
7930 // Aha, it is a pointer, just in disguise.
7931 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7934 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7935 __FILE__, __LINE__);
7940 rname++; // skip the '@'.
7945 /* otherwise get a free pointer register */
7947 preg = getFreePtr (ic, &aop, FALSE);
7948 emitcode ("mov", "%s,%s",
7950 aopGet (AOP (result), 0, FALSE, TRUE));
7956 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7959 aopOp (right, ic, FALSE);
7961 /* if bitfield then unpack the bits */
7962 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7963 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7966 /* we have can just get the values */
7967 int size = AOP_SIZE (right);
7972 l = aopGet (AOP (right), offset, FALSE, TRUE);
7976 emitcode ("mov", "@%s,a", rname);
7979 emitcode ("mov", "@%s,%s", rname, l);
7981 emitcode ("inc", "%s", rname);
7986 /* now some housekeeping stuff */
7987 if (aop) /* we had to allocate for this iCode */
7989 if (pi) aopPut (AOP (result),rname,0);
7990 freeAsmop (NULL, aop, ic, TRUE);
7994 /* we did not allocate which means left
7995 already in a pointer register, then
7996 if size > 0 && this could be used again
7997 we have to point it back to where it
7999 if ((AOP_SIZE (right) > 1 &&
8000 !OP_SYMBOL (result)->remat &&
8001 (OP_SYMBOL (result)->liveTo > ic->seq ||
8005 int size = AOP_SIZE (right) - 1;
8007 emitcode ("dec", "%s", rname);
8012 if (pi) pi->generated = 1;
8013 freeAsmop (result, NULL, ic, TRUE);
8014 freeAsmop (right, NULL, ic, TRUE);
8017 /*-----------------------------------------------------------------*/
8018 /* genPagedPointerSet - emitcode for Paged pointer put */
8019 /*-----------------------------------------------------------------*/
8021 genPagedPointerSet (operand * right,
8029 sym_link *retype, *letype;
8031 D(emitcode ("; genPagedPointerSet",""));
8033 retype = getSpec (operandType (right));
8034 letype = getSpec (operandType (result));
8036 aopOp (result, ic, FALSE);
8038 /* if the value is already in a pointer register
8039 then don't need anything more */
8040 if (!AOP_INPREG (AOP (result)))
8042 /* otherwise get a free pointer register */
8044 preg = getFreePtr (ic, &aop, FALSE);
8045 emitcode ("mov", "%s,%s",
8047 aopGet (AOP (result), 0, FALSE, TRUE));
8051 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8053 aopOp (right, ic, FALSE);
8055 /* if bitfield then unpack the bits */
8056 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8057 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8060 /* we have can just get the values */
8061 int size = AOP_SIZE (right);
8066 l = aopGet (AOP (right), offset, FALSE, TRUE);
8069 emitcode ("movx", "@%s,a", rname);
8072 emitcode ("inc", "%s", rname);
8078 /* now some housekeeping stuff */
8079 if (aop) /* we had to allocate for this iCode */
8081 if (pi) aopPut (AOP (result),rname,0);
8082 freeAsmop (NULL, aop, ic, TRUE);
8086 /* we did not allocate which means left
8087 already in a pointer register, then
8088 if size > 0 && this could be used again
8089 we have to point it back to where it
8091 if (AOP_SIZE (right) > 1 &&
8092 !OP_SYMBOL (result)->remat &&
8093 (OP_SYMBOL (result)->liveTo > ic->seq ||
8096 int size = AOP_SIZE (right) - 1;
8098 emitcode ("dec", "%s", rname);
8103 if (pi) pi->generated = 1;
8104 freeAsmop (result, NULL, ic, TRUE);
8105 freeAsmop (right, NULL, ic, TRUE);
8110 /*-----------------------------------------------------------------*/
8111 /* genFarPointerSet - set value from far space */
8112 /*-----------------------------------------------------------------*/
8114 genFarPointerSet (operand * right,
8115 operand * result, iCode * ic, iCode * pi)
8118 sym_link *retype = getSpec (operandType (right));
8119 sym_link *letype = getSpec (operandType (result));
8121 D(emitcode ("; genFarPointerSet",""));
8123 aopOp (result, ic, FALSE);
8125 /* if the operand is already in dptr
8126 then we do nothing else we move the value to dptr */
8127 if (AOP_TYPE (result) != AOP_STR)
8129 /* if this is remateriazable */
8130 if (AOP_TYPE (result) == AOP_IMMD)
8131 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8133 { /* we need to get it byte by byte */
8134 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8135 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8138 /* so dptr know contains the address */
8139 aopOp (right, ic, FALSE);
8141 /* if bit then unpack */
8142 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8143 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8146 size = AOP_SIZE (right);
8151 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8153 emitcode ("movx", "@dptr,a");
8155 emitcode ("inc", "dptr");
8158 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8159 aopPut (AOP(result),"dpl",0);
8160 aopPut (AOP(result),"dph",1);
8163 freeAsmop (result, NULL, ic, TRUE);
8164 freeAsmop (right, NULL, ic, TRUE);
8167 /*-----------------------------------------------------------------*/
8168 /* genGenPointerSet - set value from generic pointer space */
8169 /*-----------------------------------------------------------------*/
8171 genGenPointerSet (operand * right,
8172 operand * result, iCode * ic, iCode * pi)
8175 sym_link *retype = getSpec (operandType (right));
8176 sym_link *letype = getSpec (operandType (result));
8178 D(emitcode ("; genGenPointerSet",""));
8180 aopOp (result, ic, FALSE);
8182 /* if the operand is already in dptr
8183 then we do nothing else we move the value to dptr */
8184 if (AOP_TYPE (result) != AOP_STR)
8186 /* if this is remateriazable */
8187 if (AOP_TYPE (result) == AOP_IMMD)
8189 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8190 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8191 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8193 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8196 { /* we need to get it byte by byte */
8197 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8198 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8199 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8202 /* so dptr know contains the address */
8203 aopOp (right, ic, FALSE);
8205 /* if bit then unpack */
8206 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8207 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8210 size = AOP_SIZE (right);
8215 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8217 emitcode ("lcall", "__gptrput");
8219 emitcode ("inc", "dptr");
8223 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8224 aopPut (AOP(result),"dpl",0);
8225 aopPut (AOP(result),"dph",1);
8226 aopPut (AOP(result),"b",2);
8229 freeAsmop (result, NULL, ic, TRUE);
8230 freeAsmop (right, NULL, ic, TRUE);
8233 /*-----------------------------------------------------------------*/
8234 /* genPointerSet - stores the value into a pointer location */
8235 /*-----------------------------------------------------------------*/
8237 genPointerSet (iCode * ic, iCode *pi)
8239 operand *right, *result;
8240 sym_link *type, *etype;
8243 D(emitcode ("; genPointerSet",""));
8245 right = IC_RIGHT (ic);
8246 result = IC_RESULT (ic);
8248 /* depending on the type of pointer we need to
8249 move it to the correct pointer register */
8250 type = operandType (result);
8251 etype = getSpec (type);
8252 /* if left is of type of pointer then it is simple */
8253 if (IS_PTR (type) && !IS_FUNC (type->next))
8255 p_type = DCL_TYPE (type);
8259 /* we have to go by the storage class */
8260 p_type = PTR_TYPE (SPEC_OCLS (etype));
8263 /* special case when cast remat */
8264 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8265 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8266 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8267 type = operandType (result);
8268 p_type = DCL_TYPE (type);
8270 /* now that we have the pointer type we assign
8271 the pointer values */
8277 genNearPointerSet (right, result, ic, pi);
8281 genPagedPointerSet (right, result, ic, pi);
8285 genFarPointerSet (right, result, ic, pi);
8289 genGenPointerSet (right, result, ic, pi);
8293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8294 "genPointerSet: illegal pointer type");
8299 /*-----------------------------------------------------------------*/
8300 /* genIfx - generate code for Ifx statement */
8301 /*-----------------------------------------------------------------*/
8303 genIfx (iCode * ic, iCode * popIc)
8305 operand *cond = IC_COND (ic);
8308 D(emitcode ("; genIfx",""));
8310 aopOp (cond, ic, FALSE);
8312 /* get the value into acc */
8313 if (AOP_TYPE (cond) != AOP_CRY)
8317 /* the result is now in the accumulator */
8318 freeAsmop (cond, NULL, ic, TRUE);
8320 /* if there was something to be popped then do it */
8324 /* if the condition is a bit variable */
8325 if (isbit && IS_ITEMP (cond) &&
8327 genIfxJump (ic, SPIL_LOC (cond)->rname);
8328 else if (isbit && !IS_ITEMP (cond))
8329 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8331 genIfxJump (ic, "a");
8336 /*-----------------------------------------------------------------*/
8337 /* genAddrOf - generates code for address of */
8338 /*-----------------------------------------------------------------*/
8340 genAddrOf (iCode * ic)
8342 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8345 D(emitcode ("; genAddrOf",""));
8347 aopOp (IC_RESULT (ic), ic, FALSE);
8349 /* if the operand is on the stack then we
8350 need to get the stack offset of this
8354 /* if it has an offset then we need to compute
8358 emitcode ("mov", "a,_bp");
8359 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8360 ((char) (sym->stack - _G.nRegsSaved)) :
8361 ((char) sym->stack)) & 0xff);
8362 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8366 /* we can just move _bp */
8367 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8369 /* fill the result with zero */
8370 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8375 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8381 /* object not on stack then we need the name */
8382 size = AOP_SIZE (IC_RESULT (ic));
8387 char s[SDCC_NAME_MAX];
8389 sprintf (s, "#(%s >> %d)",
8393 sprintf (s, "#%s", sym->rname);
8394 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8398 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8402 /*-----------------------------------------------------------------*/
8403 /* genFarFarAssign - assignment when both are in far space */
8404 /*-----------------------------------------------------------------*/
8406 genFarFarAssign (operand * result, operand * right, iCode * ic)
8408 int size = AOP_SIZE (right);
8412 D(emitcode ("; genFarFarAssign",""));
8414 /* first push the right side on to the stack */
8417 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8419 emitcode ("push", "acc");
8422 freeAsmop (right, NULL, ic, FALSE);
8423 /* now assign DPTR to result */
8424 aopOp (result, ic, FALSE);
8425 size = AOP_SIZE (result);
8428 emitcode ("pop", "acc");
8429 aopPut (AOP (result), "a", --offset);
8431 freeAsmop (result, NULL, ic, FALSE);
8435 /*-----------------------------------------------------------------*/
8436 /* genAssign - generate code for assignment */
8437 /*-----------------------------------------------------------------*/
8439 genAssign (iCode * ic)
8441 operand *result, *right;
8443 unsigned long lit = 0L;
8445 D(emitcode("; genAssign",""));
8447 result = IC_RESULT (ic);
8448 right = IC_RIGHT (ic);
8450 /* if they are the same */
8451 if (operandsEqu (result, right)) {
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 if (!options.noCcodeInAsm) {
8923 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8924 printCLine(ic->filename, ic->lineno));
8928 if (options.iCodeInAsm) {
8929 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8931 /* if the result is marked as
8932 spilt and rematerializable or code for
8933 this has already been generated then
8935 if (resultRemat (ic) || ic->generated)
8938 /* depending on the operation */
8958 /* IPOP happens only when trying to restore a
8959 spilt live range, if there is an ifx statement
8960 following this pop then the if statement might
8961 be using some of the registers being popped which
8962 would destory the contents of the register so
8963 we need to check for this condition and handle it */
8965 ic->next->op == IFX &&
8966 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8967 genIfx (ic->next, ic);
8985 genEndFunction (ic);
9005 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9022 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9026 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9033 /* note these two are xlated by algebraic equivalence
9034 during parsing SDCC.y */
9035 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9036 "got '>=' or '<=' shouldn't have come here");
9040 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9052 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9056 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9060 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9087 case GET_VALUE_AT_ADDRESS:
9088 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9092 if (POINTER_SET (ic))
9093 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9119 addSet (&_G.sendSet, ic);
9128 /* now we are ready to call the
9129 peep hole optimizer */
9130 if (!options.nopeep)
9131 peepHole (&lineHead);
9133 /* now do the actual printing */
9134 printLine (lineHead, codeOutFile);